From 8979c70024f74fda9bd84b82a3148147e01bb390 Mon Sep 17 00:00:00 2001 From: Puneet Punamiya Date: Wed, 5 Mar 2025 01:38:24 +0000 Subject: [PATCH] Bumps goa version and updates the gen folder Signed-off-by: Puneet Punamiya --- api/gen/admin/client.go | 2 +- api/gen/admin/endpoints.go | 2 +- api/gen/admin/service.go | 2 +- api/gen/catalog/client.go | 2 +- api/gen/catalog/endpoints.go | 2 +- api/gen/catalog/service.go | 2 +- api/gen/catalog/views/view.go | 2 +- api/gen/category/client.go | 2 +- api/gen/category/endpoints.go | 2 +- api/gen/category/service.go | 2 +- api/gen/http/admin/client/cli.go | 2 +- api/gen/http/admin/client/client.go | 2 +- api/gen/http/admin/client/encode_decode.go | 2 +- api/gen/http/admin/client/paths.go | 2 +- api/gen/http/admin/client/types.go | 2 +- api/gen/http/admin/server/encode_decode.go | 2 +- api/gen/http/admin/server/paths.go | 2 +- api/gen/http/admin/server/server.go | 2 +- api/gen/http/admin/server/types.go | 2 +- api/gen/http/catalog/client/cli.go | 2 +- api/gen/http/catalog/client/client.go | 2 +- api/gen/http/catalog/client/encode_decode.go | 2 +- api/gen/http/catalog/client/paths.go | 2 +- api/gen/http/catalog/client/types.go | 2 +- api/gen/http/catalog/server/encode_decode.go | 2 +- api/gen/http/catalog/server/paths.go | 2 +- api/gen/http/catalog/server/server.go | 2 +- api/gen/http/catalog/server/types.go | 2 +- api/gen/http/category/client/cli.go | 2 +- api/gen/http/category/client/client.go | 2 +- api/gen/http/category/client/encode_decode.go | 2 +- api/gen/http/category/client/paths.go | 2 +- api/gen/http/category/client/types.go | 2 +- api/gen/http/category/server/encode_decode.go | 2 +- api/gen/http/category/server/paths.go | 2 +- api/gen/http/category/server/server.go | 2 +- api/gen/http/category/server/types.go | 2 +- api/gen/http/cli/hub/cli.go | 2 +- api/gen/http/rating/client/cli.go | 2 +- api/gen/http/rating/client/client.go | 2 +- api/gen/http/rating/client/encode_decode.go | 2 +- api/gen/http/rating/client/paths.go | 2 +- api/gen/http/rating/client/types.go | 2 +- api/gen/http/rating/server/encode_decode.go | 2 +- api/gen/http/rating/server/paths.go | 2 +- api/gen/http/rating/server/server.go | 2 +- api/gen/http/rating/server/types.go | 2 +- api/gen/http/resource/client/cli.go | 2 +- api/gen/http/resource/client/client.go | 2 +- api/gen/http/resource/client/encode_decode.go | 2 +- api/gen/http/resource/client/paths.go | 2 +- api/gen/http/resource/client/types.go | 2 +- api/gen/http/resource/server/encode_decode.go | 2 +- api/gen/http/resource/server/paths.go | 2 +- api/gen/http/resource/server/server.go | 2 +- api/gen/http/resource/server/types.go | 2 +- api/gen/http/status/client/cli.go | 2 +- api/gen/http/status/client/client.go | 2 +- api/gen/http/status/client/encode_decode.go | 2 +- api/gen/http/status/client/paths.go | 2 +- api/gen/http/status/client/types.go | 2 +- api/gen/http/status/server/encode_decode.go | 2 +- api/gen/http/status/server/paths.go | 2 +- api/gen/http/status/server/server.go | 2 +- api/gen/http/status/server/types.go | 2 +- api/gen/http/swagger/client/client.go | 2 +- api/gen/http/swagger/client/encode_decode.go | 2 +- api/gen/http/swagger/client/paths.go | 2 +- api/gen/http/swagger/client/types.go | 2 +- api/gen/http/swagger/server/paths.go | 2 +- api/gen/http/swagger/server/server.go | 2 +- api/gen/http/swagger/server/types.go | 2 +- api/gen/rating/client.go | 2 +- api/gen/rating/endpoints.go | 2 +- api/gen/rating/service.go | 2 +- api/gen/resource/client.go | 2 +- api/gen/resource/endpoints.go | 2 +- api/gen/resource/service.go | 2 +- api/gen/resource/views/view.go | 2 +- api/gen/status/client.go | 2 +- api/gen/status/endpoints.go | 2 +- api/gen/status/service.go | 2 +- api/gen/swagger/client.go | 2 +- api/gen/swagger/endpoints.go | 2 +- api/gen/swagger/service.go | 2 +- api/v1/gen/catalog/client.go | 2 +- api/v1/gen/catalog/endpoints.go | 2 +- api/v1/gen/catalog/service.go | 2 +- api/v1/gen/catalog/views/view.go | 2 +- api/v1/gen/http/catalog/client/cli.go | 2 +- api/v1/gen/http/catalog/client/client.go | 2 +- .../gen/http/catalog/client/encode_decode.go | 2 +- api/v1/gen/http/catalog/client/paths.go | 2 +- api/v1/gen/http/catalog/client/types.go | 2 +- .../gen/http/catalog/server/encode_decode.go | 2 +- api/v1/gen/http/catalog/server/paths.go | 2 +- api/v1/gen/http/catalog/server/server.go | 2 +- api/v1/gen/http/catalog/server/types.go | 2 +- api/v1/gen/http/cli/hub/cli.go | 2 +- api/v1/gen/http/resource/client/cli.go | 2 +- api/v1/gen/http/resource/client/client.go | 2 +- .../gen/http/resource/client/encode_decode.go | 2 +- api/v1/gen/http/resource/client/paths.go | 2 +- api/v1/gen/http/resource/client/types.go | 2 +- .../gen/http/resource/server/encode_decode.go | 2 +- api/v1/gen/http/resource/server/paths.go | 2 +- api/v1/gen/http/resource/server/server.go | 2 +- api/v1/gen/http/resource/server/types.go | 2 +- api/v1/gen/http/swagger/client/client.go | 2 +- .../gen/http/swagger/client/encode_decode.go | 2 +- api/v1/gen/http/swagger/client/paths.go | 2 +- api/v1/gen/http/swagger/client/types.go | 2 +- api/v1/gen/http/swagger/server/paths.go | 2 +- api/v1/gen/http/swagger/server/server.go | 2 +- api/v1/gen/http/swagger/server/types.go | 2 +- api/v1/gen/resource/client.go | 2 +- api/v1/gen/resource/endpoints.go | 2 +- api/v1/gen/resource/service.go | 2 +- api/v1/gen/resource/views/view.go | 2 +- api/v1/gen/swagger/client.go | 2 +- api/v1/gen/swagger/endpoints.go | 2 +- api/v1/gen/swagger/service.go | 2 +- go.mod | 23 +- go.sum | 48 +- test/presubmit-tests.sh | 2 +- vendor/github.com/go-chi/chi/v5/README.md | 5 +- vendor/github.com/go-chi/chi/v5/chi.go | 6 +- vendor/github.com/go-chi/chi/v5/context.go | 5 +- vendor/github.com/go-chi/chi/v5/mux.go | 31 +- .../gohugoio/hashstructure/.gitignore | 1 + .../github.com/gohugoio/hashstructure/LICENSE | 21 + .../gohugoio/hashstructure/README.md | 67 + .../gohugoio/hashstructure/errors.go | 22 + .../gohugoio/hashstructure/hashstructure.go | 488 +++++++ .../gohugoio/hashstructure/include.go | 22 + vendor/goa.design/goa/v3/codegen/cli/cli.go | 224 ++-- .../goa/v3/codegen/example/example_server.go | 20 +- .../example/templates/server_endpoints.go.tpl | 2 +- .../templates/server_interceptors.go.tpl | 19 + .../goa/v3/codegen/generator/example.go | 7 + vendor/goa.design/goa/v3/codegen/goify.go | 62 +- .../goa/v3/codegen/service/client.go | 2 +- .../goa/v3/codegen/service/convert.go | 39 +- .../goa/v3/codegen/service/endpoint.go | 31 +- .../codegen/service/example_interceptors.go | 86 ++ .../goa/v3/codegen/service/example_svc.go | 6 +- .../goa/v3/codegen/service/interceptors.go | 265 ++++ .../goa/v3/codegen/service/interceptors.md | 163 +++ .../goa/v3/codegen/service/service.go | 18 +- .../goa/v3/codegen/service/service_data.go | 1162 ++++++++++------- ...nt_interceptor_stream_wrapper_types.go.tpl | 14 + .../client_interceptor_stream_wrappers.go.tpl | 40 + .../client_interceptor_wrappers.go.tpl | 69 + .../templates/client_interceptors.go.tpl | 12 + .../service/templates/client_wrappers.go.tpl | 8 + .../templates/endpoint_wrappers.go.tpl | 7 + .../example_client_interceptor.go.tpl | 24 + ....tpl => example_security_authfuncs.go.tpl} | 0 .../example_server_interceptor.go.tpl | 24 + ...nit.go.tpl => example_service_init.go.tpl} | 0 ...t.go.tpl => example_service_struct.go.tpl} | 0 .../service/templates/interceptors.go.tpl | 254 ++++ .../templates/interceptors_types.go.tpl | 115 ++ ...er_interceptor_stream_wrapper_types.go.tpl | 14 + .../server_interceptor_stream_wrappers.go.tpl | 40 + .../server_interceptor_wrappers.go.tpl | 66 + .../templates/server_interceptors.go.tpl | 12 + .../codegen/service/templates/service.go.tpl | 4 + .../templates/service_client_init.go.tpl | 12 +- .../templates/service_endpoints_init.go.tpl | 15 +- .../goa/v3/codegen/service/testing.go | 42 + .../goa.design/goa/v3/codegen/transformer.go | 8 + vendor/goa.design/goa/v3/dsl/api.go | 12 +- vendor/goa.design/goa/v3/dsl/attribute.go | 4 +- vendor/goa.design/goa/v3/dsl/description.go | 2 + vendor/goa.design/goa/v3/dsl/http.go | 6 +- vendor/goa.design/goa/v3/dsl/interceptor.go | 389 ++++++ vendor/goa.design/goa/v3/dsl/meta.go | 90 ++ vendor/goa.design/goa/v3/dsl/result_type.go | 2 +- vendor/goa.design/goa/v3/dsl/security.go | 2 +- vendor/goa.design/goa/v3/dsl/server.go | 2 +- vendor/goa.design/goa/v3/dsl/user_type.go | 2 +- vendor/goa.design/goa/v3/expr/api.go | 6 +- vendor/goa.design/goa/v3/expr/attribute.go | 6 + .../goa.design/goa/v3/expr/http_body_types.go | 16 +- .../goa.design/goa/v3/expr/http_endpoint.go | 4 +- vendor/goa.design/goa/v3/expr/interceptor.go | 124 ++ vendor/goa.design/goa/v3/expr/method.go | 72 +- vendor/goa.design/goa/v3/expr/root.go | 5 + vendor/goa.design/goa/v3/expr/service.go | 4 + .../codegen/client-no-server-pkgpath.golden | 17 - .../v3/grpc/codegen/client-no-server.golden | 17 - ...r-hosting-multiple-services-pkgpath.golden | 17 - ...nt-server-hosting-multiple-services.golden | 17 - ...rver-hosting-service-subset-pkgpath.golden | 17 - ...lient-server-hosting-service-subset.golden | 17 - .../goa.design/goa/v3/grpc/codegen/client.go | 2 +- .../goa/v3/grpc/codegen/client_cli.go | 60 +- .../goa/v3/grpc/codegen/example_cli.go | 29 +- .../goa.design/goa/v3/grpc/codegen/proto.go | 20 +- .../goa/v3/grpc/codegen/service_data.go | 751 +++++------ .../templates/client_endpoint_init.go.tpl | 6 +- .../grpc/codegen/templates/do_grpc_cli.go.tpl | 14 +- .../codegen/templates/parse_endpoint.go.tpl | 18 +- .../grpc/codegen/templates/stream_recv.go.tpl | 5 + .../grpc/codegen/templates/stream_send.go.tpl | 5 + .../goa.design/goa/v3/http/codegen/client.go | 2 +- .../goa/v3/http/codegen/client_cli.go | 11 +- .../goa/v3/http/codegen/example_cli.go | 34 +- .../v3/http/codegen/openapi/json_schema.go | 12 + .../goa/v3/http/codegen/openapi/v3/types.go | 46 +- .../goa.design/goa/v3/http/codegen/server.go | 21 +- .../goa/v3/http/codegen/service_data.go | 55 +- .../v3/http/codegen/templates/cli_end.go.tpl | 29 +- .../http/codegen/templates/cli_start.go.tpl | 10 + .../codegen/templates/parse_endpoint.go.tpl | 13 +- .../codegen/templates/websocket_recv.go.tpl | 5 + .../codegen/templates/websocket_send.go.tpl | 5 + .../goa/v3/http/codegen/websocket.go | 288 ++-- vendor/goa.design/goa/v3/pkg/interceptor.go | 30 + vendor/goa.design/goa/v3/pkg/version.go | 4 +- vendor/golang.org/x/net/http2/http2.go | 39 +- vendor/golang.org/x/net/http2/server.go | 4 +- vendor/golang.org/x/net/http2/transport.go | 330 +---- vendor/golang.org/x/net/http2/write.go | 3 +- .../x/net/internal/httpcommon/ascii.go | 53 + .../httpcommon}/headermap.go | 18 +- .../x/net/internal/httpcommon/request.go | 379 ++++++ .../x/tools/go/ast/astutil/imports.go | 5 + .../golang.org/x/tools/go/ast/astutil/util.go | 12 +- .../x/tools/go/gcexportdata/gcexportdata.go | 119 +- vendor/golang.org/x/tools/go/packages/doc.go | 15 +- .../x/tools/go/packages/external.go | 13 +- .../golang.org/x/tools/go/packages/golist.go | 48 +- .../x/tools/go/packages/loadmode_string.go | 71 +- .../x/tools/go/packages/packages.go | 398 +++--- .../x/tools/go/types/objectpath/objectpath.go | 111 +- .../x/tools/go/types/typeutil/callee.go | 68 + .../x/tools/go/types/typeutil/imports.go | 30 + .../x/tools/go/types/typeutil/map.go | 470 +++++++ .../tools/go/types/typeutil/methodsetcache.go | 71 + .../x/tools/go/types/typeutil/ui.go | 53 + .../x/tools/internal/aliases/aliases.go | 2 +- .../x/tools/internal/aliases/aliases_go121.go | 37 - .../x/tools/internal/aliases/aliases_go122.go | 32 +- .../x/tools/internal/gcimporter/bimport.go | 61 - .../x/tools/internal/gcimporter/exportdata.go | 426 +++++- .../x/tools/internal/gcimporter/gcimporter.go | 182 +-- .../x/tools/internal/gcimporter/iexport.go | 37 +- .../x/tools/internal/gcimporter/iimport.go | 37 +- .../internal/gcimporter/iimport_go122.go | 53 + .../internal/gcimporter/newInterface10.go | 22 - .../internal/gcimporter/newInterface11.go | 14 - .../tools/internal/gcimporter/predeclared.go | 91 ++ .../x/tools/internal/gcimporter/support.go | 30 + .../internal/gcimporter/support_go118.go | 34 - .../x/tools/internal/gcimporter/unified_no.go | 10 - .../tools/internal/gcimporter/unified_yes.go | 10 - .../tools/internal/gcimporter/ureader_yes.go | 31 +- .../x/tools/internal/gocommand/invoke.go | 60 +- .../internal/gocommand/invoke_notunix.go | 13 + .../x/tools/internal/gocommand/invoke_unix.go | 13 + .../x/tools/internal/imports/fix.go | 251 ++-- .../x/tools/internal/imports/imports.go | 33 +- .../x/tools/internal/imports/source.go | 63 + .../x/tools/internal/imports/source_env.go | 129 ++ .../tools/internal/imports/source_modindex.go | 103 ++ .../x/tools/internal/modindex/directories.go | 135 ++ .../x/tools/internal/modindex/index.go | 266 ++++ .../x/tools/internal/modindex/lookup.go | 178 +++ .../x/tools/internal/modindex/modindex.go | 164 +++ .../x/tools/internal/modindex/symbols.go | 218 ++++ .../x/tools/internal/modindex/types.go | 25 + .../internal/packagesinternal/packages.go | 6 +- .../x/tools/internal/stdlib/manifest.go | 219 ++++ .../internal/tokeninternal/tokeninternal.go | 137 -- .../x/tools/internal/typeparams/common.go | 68 + .../x/tools/internal/typeparams/coretype.go | 155 +++ .../x/tools/internal/typeparams/free.go | 131 ++ .../x/tools/internal/typeparams/normalize.go | 218 ++++ .../x/tools/internal/typeparams/termlist.go | 163 +++ .../x/tools/internal/typeparams/typeterm.go | 169 +++ .../x/tools/internal/typesinternal/element.go | 133 ++ .../tools/internal/typesinternal/errorcode.go | 2 +- .../tools/internal/typesinternal/qualifier.go | 46 + .../x/tools/internal/typesinternal/recv.go | 11 +- .../x/tools/internal/typesinternal/types.go | 62 + .../x/tools/internal/typesinternal/varkind.go | 40 + .../tools/internal/typesinternal/zerovalue.go | 392 ++++++ .../x/tools/internal/versions/constraint.go | 13 - .../internal/versions/constraint_go121.go | 14 - .../x/tools/internal/versions/toolchain.go | 14 - .../internal/versions/toolchain_go119.go | 14 - .../internal/versions/toolchain_go120.go | 14 - .../internal/versions/toolchain_go121.go | 14 - .../x/tools/internal/versions/types.go | 28 +- .../x/tools/internal/versions/types_go121.go | 30 - .../x/tools/internal/versions/types_go122.go | 41 - .../protobuf/encoding/protojson/decode.go | 5 - .../protobuf/encoding/prototext/decode.go | 5 - .../protobuf/internal/encoding/tag/tag.go | 8 +- .../protobuf/internal/filedesc/desc.go | 9 +- .../protobuf/internal/filedesc/desc_lazy.go | 9 - .../protobuf/internal/filetype/build.go | 2 +- .../protobuf/internal/flags/flags.go | 7 +- .../protobuf/internal/genid/goname.go | 5 - .../protobuf/internal/impl/codec_field.go | 75 -- .../protobuf/internal/impl/codec_message.go | 3 - .../internal/impl/codec_message_opaque.go | 3 - .../protobuf/internal/impl/lazy.go | 2 +- .../protobuf/internal/impl/legacy_message.go | 5 +- .../protobuf/internal/impl/message.go | 13 - .../protobuf/internal/impl/message_opaque.go | 5 - .../protobuf/internal/impl/message_reflect.go | 5 - .../internal/impl/message_reflect_field.go | 76 -- .../protobuf/internal/impl/pointer_unsafe.go | 1 - .../protobuf/internal/impl/validate.go | 24 +- .../protobuf/internal/impl/weak.go | 74 -- .../protobuf/internal/version/version.go | 2 +- .../protobuf/proto/decode.go | 5 - .../protobuf/reflect/protodesc/desc.go | 8 +- .../protobuf/reflect/protodesc/desc_init.go | 1 - .../reflect/protodesc/desc_resolve.go | 26 +- .../reflect/protodesc/desc_validate.go | 12 - .../protobuf/reflect/protodesc/proto.go | 3 - .../protobuf/reflect/protoreflect/type.go | 12 +- vendor/modules.txt | 34 +- 327 files changed, 10160 insertions(+), 3679 deletions(-) create mode 100644 vendor/github.com/gohugoio/hashstructure/.gitignore create mode 100644 vendor/github.com/gohugoio/hashstructure/LICENSE create mode 100644 vendor/github.com/gohugoio/hashstructure/README.md create mode 100644 vendor/github.com/gohugoio/hashstructure/errors.go create mode 100644 vendor/github.com/gohugoio/hashstructure/hashstructure.go create mode 100644 vendor/github.com/gohugoio/hashstructure/include.go create mode 100644 vendor/goa.design/goa/v3/codegen/example/templates/server_interceptors.go.tpl create mode 100644 vendor/goa.design/goa/v3/codegen/service/example_interceptors.go create mode 100644 vendor/goa.design/goa/v3/codegen/service/interceptors.go create mode 100644 vendor/goa.design/goa/v3/codegen/service/interceptors.md create mode 100644 vendor/goa.design/goa/v3/codegen/service/templates/client_interceptor_stream_wrapper_types.go.tpl create mode 100644 vendor/goa.design/goa/v3/codegen/service/templates/client_interceptor_stream_wrappers.go.tpl create mode 100644 vendor/goa.design/goa/v3/codegen/service/templates/client_interceptor_wrappers.go.tpl create mode 100644 vendor/goa.design/goa/v3/codegen/service/templates/client_interceptors.go.tpl create mode 100644 vendor/goa.design/goa/v3/codegen/service/templates/client_wrappers.go.tpl create mode 100644 vendor/goa.design/goa/v3/codegen/service/templates/endpoint_wrappers.go.tpl create mode 100644 vendor/goa.design/goa/v3/codegen/service/templates/example_client_interceptor.go.tpl rename vendor/goa.design/goa/v3/codegen/service/templates/{security_authfuncs.go.tpl => example_security_authfuncs.go.tpl} (100%) create mode 100644 vendor/goa.design/goa/v3/codegen/service/templates/example_server_interceptor.go.tpl rename vendor/goa.design/goa/v3/codegen/service/templates/{service_init.go.tpl => example_service_init.go.tpl} (100%) rename vendor/goa.design/goa/v3/codegen/service/templates/{service_struct.go.tpl => example_service_struct.go.tpl} (100%) create mode 100644 vendor/goa.design/goa/v3/codegen/service/templates/interceptors.go.tpl create mode 100644 vendor/goa.design/goa/v3/codegen/service/templates/interceptors_types.go.tpl create mode 100644 vendor/goa.design/goa/v3/codegen/service/templates/server_interceptor_stream_wrapper_types.go.tpl create mode 100644 vendor/goa.design/goa/v3/codegen/service/templates/server_interceptor_stream_wrappers.go.tpl create mode 100644 vendor/goa.design/goa/v3/codegen/service/templates/server_interceptor_wrappers.go.tpl create mode 100644 vendor/goa.design/goa/v3/codegen/service/templates/server_interceptors.go.tpl create mode 100644 vendor/goa.design/goa/v3/codegen/service/testing.go create mode 100644 vendor/goa.design/goa/v3/dsl/interceptor.go create mode 100644 vendor/goa.design/goa/v3/expr/interceptor.go delete mode 100644 vendor/goa.design/goa/v3/grpc/codegen/client-no-server-pkgpath.golden delete mode 100644 vendor/goa.design/goa/v3/grpc/codegen/client-no-server.golden delete mode 100644 vendor/goa.design/goa/v3/grpc/codegen/client-server-hosting-multiple-services-pkgpath.golden delete mode 100644 vendor/goa.design/goa/v3/grpc/codegen/client-server-hosting-multiple-services.golden delete mode 100644 vendor/goa.design/goa/v3/grpc/codegen/client-server-hosting-service-subset-pkgpath.golden delete mode 100644 vendor/goa.design/goa/v3/grpc/codegen/client-server-hosting-service-subset.golden create mode 100644 vendor/goa.design/goa/v3/pkg/interceptor.go create mode 100644 vendor/golang.org/x/net/internal/httpcommon/ascii.go rename vendor/golang.org/x/net/{http2 => internal/httpcommon}/headermap.go (77%) create mode 100644 vendor/golang.org/x/net/internal/httpcommon/request.go create mode 100644 vendor/golang.org/x/tools/go/types/typeutil/callee.go create mode 100644 vendor/golang.org/x/tools/go/types/typeutil/imports.go create mode 100644 vendor/golang.org/x/tools/go/types/typeutil/map.go create mode 100644 vendor/golang.org/x/tools/go/types/typeutil/methodsetcache.go create mode 100644 vendor/golang.org/x/tools/go/types/typeutil/ui.go delete mode 100644 vendor/golang.org/x/tools/internal/aliases/aliases_go121.go create mode 100644 vendor/golang.org/x/tools/internal/gcimporter/iimport_go122.go delete mode 100644 vendor/golang.org/x/tools/internal/gcimporter/newInterface10.go delete mode 100644 vendor/golang.org/x/tools/internal/gcimporter/newInterface11.go create mode 100644 vendor/golang.org/x/tools/internal/gcimporter/predeclared.go create mode 100644 vendor/golang.org/x/tools/internal/gcimporter/support.go delete mode 100644 vendor/golang.org/x/tools/internal/gcimporter/support_go118.go delete mode 100644 vendor/golang.org/x/tools/internal/gcimporter/unified_no.go delete mode 100644 vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go create mode 100644 vendor/golang.org/x/tools/internal/gocommand/invoke_notunix.go create mode 100644 vendor/golang.org/x/tools/internal/gocommand/invoke_unix.go create mode 100644 vendor/golang.org/x/tools/internal/imports/source.go create mode 100644 vendor/golang.org/x/tools/internal/imports/source_env.go create mode 100644 vendor/golang.org/x/tools/internal/imports/source_modindex.go create mode 100644 vendor/golang.org/x/tools/internal/modindex/directories.go create mode 100644 vendor/golang.org/x/tools/internal/modindex/index.go create mode 100644 vendor/golang.org/x/tools/internal/modindex/lookup.go create mode 100644 vendor/golang.org/x/tools/internal/modindex/modindex.go create mode 100644 vendor/golang.org/x/tools/internal/modindex/symbols.go create mode 100644 vendor/golang.org/x/tools/internal/modindex/types.go delete mode 100644 vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go create mode 100644 vendor/golang.org/x/tools/internal/typeparams/common.go create mode 100644 vendor/golang.org/x/tools/internal/typeparams/coretype.go create mode 100644 vendor/golang.org/x/tools/internal/typeparams/free.go create mode 100644 vendor/golang.org/x/tools/internal/typeparams/normalize.go create mode 100644 vendor/golang.org/x/tools/internal/typeparams/termlist.go create mode 100644 vendor/golang.org/x/tools/internal/typeparams/typeterm.go create mode 100644 vendor/golang.org/x/tools/internal/typesinternal/element.go create mode 100644 vendor/golang.org/x/tools/internal/typesinternal/qualifier.go create mode 100644 vendor/golang.org/x/tools/internal/typesinternal/varkind.go create mode 100644 vendor/golang.org/x/tools/internal/typesinternal/zerovalue.go delete mode 100644 vendor/golang.org/x/tools/internal/versions/constraint.go delete mode 100644 vendor/golang.org/x/tools/internal/versions/constraint_go121.go delete mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain.go delete mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain_go119.go delete mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain_go120.go delete mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain_go121.go delete mode 100644 vendor/golang.org/x/tools/internal/versions/types_go121.go delete mode 100644 vendor/golang.org/x/tools/internal/versions/types_go122.go delete mode 100644 vendor/google.golang.org/protobuf/internal/impl/weak.go diff --git a/api/gen/admin/client.go b/api/gen/admin/client.go index 0ea9640e2a..14270a06f7 100644 --- a/api/gen/admin/client.go +++ b/api/gen/admin/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // admin client // diff --git a/api/gen/admin/endpoints.go b/api/gen/admin/endpoints.go index 1c50423161..3dfee664ce 100644 --- a/api/gen/admin/endpoints.go +++ b/api/gen/admin/endpoints.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // admin endpoints // diff --git a/api/gen/admin/service.go b/api/gen/admin/service.go index 6e8cfffda7..aaf845e355 100644 --- a/api/gen/admin/service.go +++ b/api/gen/admin/service.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // admin service // diff --git a/api/gen/catalog/client.go b/api/gen/catalog/client.go index 65f349eee0..db39bddaa8 100644 --- a/api/gen/catalog/client.go +++ b/api/gen/catalog/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog client // diff --git a/api/gen/catalog/endpoints.go b/api/gen/catalog/endpoints.go index 9c6268b370..f499aa9dc3 100644 --- a/api/gen/catalog/endpoints.go +++ b/api/gen/catalog/endpoints.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog endpoints // diff --git a/api/gen/catalog/service.go b/api/gen/catalog/service.go index f19ca672fa..3743a071a6 100644 --- a/api/gen/catalog/service.go +++ b/api/gen/catalog/service.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog service // diff --git a/api/gen/catalog/views/view.go b/api/gen/catalog/views/view.go index 00a0bf3f59..cc3729c01d 100644 --- a/api/gen/catalog/views/view.go +++ b/api/gen/catalog/views/view.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog views // diff --git a/api/gen/category/client.go b/api/gen/category/client.go index 401464c34f..d020baeda2 100644 --- a/api/gen/category/client.go +++ b/api/gen/category/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // category client // diff --git a/api/gen/category/endpoints.go b/api/gen/category/endpoints.go index 1b4a240d98..f89908407a 100644 --- a/api/gen/category/endpoints.go +++ b/api/gen/category/endpoints.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // category endpoints // diff --git a/api/gen/category/service.go b/api/gen/category/service.go index 991e4baee8..ee43e85148 100644 --- a/api/gen/category/service.go +++ b/api/gen/category/service.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // category service // diff --git a/api/gen/http/admin/client/cli.go b/api/gen/http/admin/client/cli.go index fc5bee8c49..7ed60dcacc 100644 --- a/api/gen/http/admin/client/cli.go +++ b/api/gen/http/admin/client/cli.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // admin HTTP client CLI support package // diff --git a/api/gen/http/admin/client/client.go b/api/gen/http/admin/client/client.go index e143a0b076..e35eb5214f 100644 --- a/api/gen/http/admin/client/client.go +++ b/api/gen/http/admin/client/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // admin client HTTP transport // diff --git a/api/gen/http/admin/client/encode_decode.go b/api/gen/http/admin/client/encode_decode.go index eaca2ccd78..1b43525191 100644 --- a/api/gen/http/admin/client/encode_decode.go +++ b/api/gen/http/admin/client/encode_decode.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // admin HTTP client encoders and decoders // diff --git a/api/gen/http/admin/client/paths.go b/api/gen/http/admin/client/paths.go index e1575299de..aece576685 100644 --- a/api/gen/http/admin/client/paths.go +++ b/api/gen/http/admin/client/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the admin service. // diff --git a/api/gen/http/admin/client/types.go b/api/gen/http/admin/client/types.go index 12d603d6f0..29189d0482 100644 --- a/api/gen/http/admin/client/types.go +++ b/api/gen/http/admin/client/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // admin HTTP client types // diff --git a/api/gen/http/admin/server/encode_decode.go b/api/gen/http/admin/server/encode_decode.go index 3120df13ff..fc038b87e1 100644 --- a/api/gen/http/admin/server/encode_decode.go +++ b/api/gen/http/admin/server/encode_decode.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // admin HTTP server encoders and decoders // diff --git a/api/gen/http/admin/server/paths.go b/api/gen/http/admin/server/paths.go index c01aefbe7b..2fcc644a71 100644 --- a/api/gen/http/admin/server/paths.go +++ b/api/gen/http/admin/server/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the admin service. // diff --git a/api/gen/http/admin/server/server.go b/api/gen/http/admin/server/server.go index 9a8f2de2ce..e443f9848d 100644 --- a/api/gen/http/admin/server/server.go +++ b/api/gen/http/admin/server/server.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // admin HTTP server // diff --git a/api/gen/http/admin/server/types.go b/api/gen/http/admin/server/types.go index d401cc1355..0bf61a0a8f 100644 --- a/api/gen/http/admin/server/types.go +++ b/api/gen/http/admin/server/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // admin HTTP server types // diff --git a/api/gen/http/catalog/client/cli.go b/api/gen/http/catalog/client/cli.go index 9ce7d17b91..c84bcd6fa8 100644 --- a/api/gen/http/catalog/client/cli.go +++ b/api/gen/http/catalog/client/cli.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog HTTP client CLI support package // diff --git a/api/gen/http/catalog/client/client.go b/api/gen/http/catalog/client/client.go index 05e04d418b..e276f828cd 100644 --- a/api/gen/http/catalog/client/client.go +++ b/api/gen/http/catalog/client/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog client HTTP transport // diff --git a/api/gen/http/catalog/client/encode_decode.go b/api/gen/http/catalog/client/encode_decode.go index 3c7d87ec50..13eb67e811 100644 --- a/api/gen/http/catalog/client/encode_decode.go +++ b/api/gen/http/catalog/client/encode_decode.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog HTTP client encoders and decoders // diff --git a/api/gen/http/catalog/client/paths.go b/api/gen/http/catalog/client/paths.go index df90b9872a..d4abf26259 100644 --- a/api/gen/http/catalog/client/paths.go +++ b/api/gen/http/catalog/client/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the catalog service. // diff --git a/api/gen/http/catalog/client/types.go b/api/gen/http/catalog/client/types.go index 9d8e8c2cfd..0442377dca 100644 --- a/api/gen/http/catalog/client/types.go +++ b/api/gen/http/catalog/client/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog HTTP client types // diff --git a/api/gen/http/catalog/server/encode_decode.go b/api/gen/http/catalog/server/encode_decode.go index 5683b97ebe..01d11dce07 100644 --- a/api/gen/http/catalog/server/encode_decode.go +++ b/api/gen/http/catalog/server/encode_decode.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog HTTP server encoders and decoders // diff --git a/api/gen/http/catalog/server/paths.go b/api/gen/http/catalog/server/paths.go index 6d3e40c3cc..ba19fa2b53 100644 --- a/api/gen/http/catalog/server/paths.go +++ b/api/gen/http/catalog/server/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the catalog service. // diff --git a/api/gen/http/catalog/server/server.go b/api/gen/http/catalog/server/server.go index 5d6dd862fb..a68de76251 100644 --- a/api/gen/http/catalog/server/server.go +++ b/api/gen/http/catalog/server/server.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog HTTP server // diff --git a/api/gen/http/catalog/server/types.go b/api/gen/http/catalog/server/types.go index 06dce0123e..5a94852189 100644 --- a/api/gen/http/catalog/server/types.go +++ b/api/gen/http/catalog/server/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog HTTP server types // diff --git a/api/gen/http/category/client/cli.go b/api/gen/http/category/client/cli.go index a944d2f9c0..91683f5079 100644 --- a/api/gen/http/category/client/cli.go +++ b/api/gen/http/category/client/cli.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // category HTTP client CLI support package // diff --git a/api/gen/http/category/client/client.go b/api/gen/http/category/client/client.go index 2d70b1a9e3..28e39f593a 100644 --- a/api/gen/http/category/client/client.go +++ b/api/gen/http/category/client/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // category client HTTP transport // diff --git a/api/gen/http/category/client/encode_decode.go b/api/gen/http/category/client/encode_decode.go index 422c25fdfc..26844bcc3c 100644 --- a/api/gen/http/category/client/encode_decode.go +++ b/api/gen/http/category/client/encode_decode.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // category HTTP client encoders and decoders // diff --git a/api/gen/http/category/client/paths.go b/api/gen/http/category/client/paths.go index 3e787ff4ff..9de350958e 100644 --- a/api/gen/http/category/client/paths.go +++ b/api/gen/http/category/client/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the category service. // diff --git a/api/gen/http/category/client/types.go b/api/gen/http/category/client/types.go index a6cfc06d21..2ba3ce8109 100644 --- a/api/gen/http/category/client/types.go +++ b/api/gen/http/category/client/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // category HTTP client types // diff --git a/api/gen/http/category/server/encode_decode.go b/api/gen/http/category/server/encode_decode.go index 83b9d98bea..1900a774e1 100644 --- a/api/gen/http/category/server/encode_decode.go +++ b/api/gen/http/category/server/encode_decode.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // category HTTP server encoders and decoders // diff --git a/api/gen/http/category/server/paths.go b/api/gen/http/category/server/paths.go index 29457b5085..b23155b40c 100644 --- a/api/gen/http/category/server/paths.go +++ b/api/gen/http/category/server/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the category service. // diff --git a/api/gen/http/category/server/server.go b/api/gen/http/category/server/server.go index f0950e3d66..d0cc9a85e9 100644 --- a/api/gen/http/category/server/server.go +++ b/api/gen/http/category/server/server.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // category HTTP server // diff --git a/api/gen/http/category/server/types.go b/api/gen/http/category/server/types.go index 1f3212896a..01162fdd50 100644 --- a/api/gen/http/category/server/types.go +++ b/api/gen/http/category/server/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // category HTTP server types // diff --git a/api/gen/http/cli/hub/cli.go b/api/gen/http/cli/hub/cli.go index 959cd5583b..4011b43871 100644 --- a/api/gen/http/cli/hub/cli.go +++ b/api/gen/http/cli/hub/cli.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // hub HTTP client CLI support package // diff --git a/api/gen/http/rating/client/cli.go b/api/gen/http/rating/client/cli.go index ac1406cebd..ade3875586 100644 --- a/api/gen/http/rating/client/cli.go +++ b/api/gen/http/rating/client/cli.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // rating HTTP client CLI support package // diff --git a/api/gen/http/rating/client/client.go b/api/gen/http/rating/client/client.go index 2f9fac881e..6482503a19 100644 --- a/api/gen/http/rating/client/client.go +++ b/api/gen/http/rating/client/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // rating client HTTP transport // diff --git a/api/gen/http/rating/client/encode_decode.go b/api/gen/http/rating/client/encode_decode.go index f09f1690b6..8bedd77782 100644 --- a/api/gen/http/rating/client/encode_decode.go +++ b/api/gen/http/rating/client/encode_decode.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // rating HTTP client encoders and decoders // diff --git a/api/gen/http/rating/client/paths.go b/api/gen/http/rating/client/paths.go index 751ef6af92..72bd2f0690 100644 --- a/api/gen/http/rating/client/paths.go +++ b/api/gen/http/rating/client/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the rating service. // diff --git a/api/gen/http/rating/client/types.go b/api/gen/http/rating/client/types.go index ff3ad50328..e0864efe11 100644 --- a/api/gen/http/rating/client/types.go +++ b/api/gen/http/rating/client/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // rating HTTP client types // diff --git a/api/gen/http/rating/server/encode_decode.go b/api/gen/http/rating/server/encode_decode.go index 16f7aae6a5..c4531dc929 100644 --- a/api/gen/http/rating/server/encode_decode.go +++ b/api/gen/http/rating/server/encode_decode.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // rating HTTP server encoders and decoders // diff --git a/api/gen/http/rating/server/paths.go b/api/gen/http/rating/server/paths.go index c5ca731932..4a20a9485f 100644 --- a/api/gen/http/rating/server/paths.go +++ b/api/gen/http/rating/server/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the rating service. // diff --git a/api/gen/http/rating/server/server.go b/api/gen/http/rating/server/server.go index 6a3dc9ded3..2284ed51a6 100644 --- a/api/gen/http/rating/server/server.go +++ b/api/gen/http/rating/server/server.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // rating HTTP server // diff --git a/api/gen/http/rating/server/types.go b/api/gen/http/rating/server/types.go index b7eede1c73..a46eacc30a 100644 --- a/api/gen/http/rating/server/types.go +++ b/api/gen/http/rating/server/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // rating HTTP server types // diff --git a/api/gen/http/resource/client/cli.go b/api/gen/http/resource/client/cli.go index f28f2da864..a1b10fb55f 100644 --- a/api/gen/http/resource/client/cli.go +++ b/api/gen/http/resource/client/cli.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource HTTP client CLI support package // diff --git a/api/gen/http/resource/client/client.go b/api/gen/http/resource/client/client.go index e17efc97df..7c036217fa 100644 --- a/api/gen/http/resource/client/client.go +++ b/api/gen/http/resource/client/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource client HTTP transport // diff --git a/api/gen/http/resource/client/encode_decode.go b/api/gen/http/resource/client/encode_decode.go index f2ed53ab02..a4afa9b854 100644 --- a/api/gen/http/resource/client/encode_decode.go +++ b/api/gen/http/resource/client/encode_decode.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource HTTP client encoders and decoders // diff --git a/api/gen/http/resource/client/paths.go b/api/gen/http/resource/client/paths.go index 74559446ec..f3196e4123 100644 --- a/api/gen/http/resource/client/paths.go +++ b/api/gen/http/resource/client/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the resource service. // diff --git a/api/gen/http/resource/client/types.go b/api/gen/http/resource/client/types.go index b09d8671d9..bc9710f80d 100644 --- a/api/gen/http/resource/client/types.go +++ b/api/gen/http/resource/client/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource HTTP client types // diff --git a/api/gen/http/resource/server/encode_decode.go b/api/gen/http/resource/server/encode_decode.go index cefe209ef5..2d8ec74380 100644 --- a/api/gen/http/resource/server/encode_decode.go +++ b/api/gen/http/resource/server/encode_decode.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource HTTP server encoders and decoders // diff --git a/api/gen/http/resource/server/paths.go b/api/gen/http/resource/server/paths.go index ee278351e2..0784081ccf 100644 --- a/api/gen/http/resource/server/paths.go +++ b/api/gen/http/resource/server/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the resource service. // diff --git a/api/gen/http/resource/server/server.go b/api/gen/http/resource/server/server.go index 458cfb6081..b5e3c70137 100644 --- a/api/gen/http/resource/server/server.go +++ b/api/gen/http/resource/server/server.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource HTTP server // diff --git a/api/gen/http/resource/server/types.go b/api/gen/http/resource/server/types.go index 6ed8ff66c6..f4e8748e42 100644 --- a/api/gen/http/resource/server/types.go +++ b/api/gen/http/resource/server/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource HTTP server types // diff --git a/api/gen/http/status/client/cli.go b/api/gen/http/status/client/cli.go index 117cc07632..0584590854 100644 --- a/api/gen/http/status/client/cli.go +++ b/api/gen/http/status/client/cli.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // status HTTP client CLI support package // diff --git a/api/gen/http/status/client/client.go b/api/gen/http/status/client/client.go index bc9f95c735..d863998ff1 100644 --- a/api/gen/http/status/client/client.go +++ b/api/gen/http/status/client/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // status client HTTP transport // diff --git a/api/gen/http/status/client/encode_decode.go b/api/gen/http/status/client/encode_decode.go index 0ded5d326b..ab7cd2d601 100644 --- a/api/gen/http/status/client/encode_decode.go +++ b/api/gen/http/status/client/encode_decode.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // status HTTP client encoders and decoders // diff --git a/api/gen/http/status/client/paths.go b/api/gen/http/status/client/paths.go index 60f9c6a854..e0a82cab38 100644 --- a/api/gen/http/status/client/paths.go +++ b/api/gen/http/status/client/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the status service. // diff --git a/api/gen/http/status/client/types.go b/api/gen/http/status/client/types.go index 3094515442..39a6e0a197 100644 --- a/api/gen/http/status/client/types.go +++ b/api/gen/http/status/client/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // status HTTP client types // diff --git a/api/gen/http/status/server/encode_decode.go b/api/gen/http/status/server/encode_decode.go index 5fb43a951d..b661f6b652 100644 --- a/api/gen/http/status/server/encode_decode.go +++ b/api/gen/http/status/server/encode_decode.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // status HTTP server encoders and decoders // diff --git a/api/gen/http/status/server/paths.go b/api/gen/http/status/server/paths.go index 8c824ce649..a70ad18ecb 100644 --- a/api/gen/http/status/server/paths.go +++ b/api/gen/http/status/server/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the status service. // diff --git a/api/gen/http/status/server/server.go b/api/gen/http/status/server/server.go index e1e7db6864..f98110909a 100644 --- a/api/gen/http/status/server/server.go +++ b/api/gen/http/status/server/server.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // status HTTP server // diff --git a/api/gen/http/status/server/types.go b/api/gen/http/status/server/types.go index 33fc260f02..f4f9beff06 100644 --- a/api/gen/http/status/server/types.go +++ b/api/gen/http/status/server/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // status HTTP server types // diff --git a/api/gen/http/swagger/client/client.go b/api/gen/http/swagger/client/client.go index a9843b8f49..74cf70298b 100644 --- a/api/gen/http/swagger/client/client.go +++ b/api/gen/http/swagger/client/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // swagger client HTTP transport // diff --git a/api/gen/http/swagger/client/encode_decode.go b/api/gen/http/swagger/client/encode_decode.go index 21f1a61216..8008692a00 100644 --- a/api/gen/http/swagger/client/encode_decode.go +++ b/api/gen/http/swagger/client/encode_decode.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // swagger HTTP client encoders and decoders // diff --git a/api/gen/http/swagger/client/paths.go b/api/gen/http/swagger/client/paths.go index d75d950bf3..00b7a2f3f4 100644 --- a/api/gen/http/swagger/client/paths.go +++ b/api/gen/http/swagger/client/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the swagger service. // diff --git a/api/gen/http/swagger/client/types.go b/api/gen/http/swagger/client/types.go index a23bbd0086..a40aa0e67f 100644 --- a/api/gen/http/swagger/client/types.go +++ b/api/gen/http/swagger/client/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // swagger HTTP client types // diff --git a/api/gen/http/swagger/server/paths.go b/api/gen/http/swagger/server/paths.go index 5609bdd8cc..9bb57cd4ce 100644 --- a/api/gen/http/swagger/server/paths.go +++ b/api/gen/http/swagger/server/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the swagger service. // diff --git a/api/gen/http/swagger/server/server.go b/api/gen/http/swagger/server/server.go index faf68ac001..5d404ff07f 100644 --- a/api/gen/http/swagger/server/server.go +++ b/api/gen/http/swagger/server/server.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // swagger HTTP server // diff --git a/api/gen/http/swagger/server/types.go b/api/gen/http/swagger/server/types.go index b1e7bc9755..e0fbd9a972 100644 --- a/api/gen/http/swagger/server/types.go +++ b/api/gen/http/swagger/server/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // swagger HTTP server types // diff --git a/api/gen/rating/client.go b/api/gen/rating/client.go index a270cb9fcb..4e1c9ed4a7 100644 --- a/api/gen/rating/client.go +++ b/api/gen/rating/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // rating client // diff --git a/api/gen/rating/endpoints.go b/api/gen/rating/endpoints.go index 0bd9234d43..b67687d6fd 100644 --- a/api/gen/rating/endpoints.go +++ b/api/gen/rating/endpoints.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // rating endpoints // diff --git a/api/gen/rating/service.go b/api/gen/rating/service.go index 68080af0d7..c2f7054b0a 100644 --- a/api/gen/rating/service.go +++ b/api/gen/rating/service.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // rating service // diff --git a/api/gen/resource/client.go b/api/gen/resource/client.go index 42208547f3..b1df3ea962 100644 --- a/api/gen/resource/client.go +++ b/api/gen/resource/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource client // diff --git a/api/gen/resource/endpoints.go b/api/gen/resource/endpoints.go index 4dee815650..c51104dd0d 100644 --- a/api/gen/resource/endpoints.go +++ b/api/gen/resource/endpoints.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource endpoints // diff --git a/api/gen/resource/service.go b/api/gen/resource/service.go index dd59d47481..d180dd7772 100644 --- a/api/gen/resource/service.go +++ b/api/gen/resource/service.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource service // diff --git a/api/gen/resource/views/view.go b/api/gen/resource/views/view.go index db50e1ac13..65bd27e8de 100644 --- a/api/gen/resource/views/view.go +++ b/api/gen/resource/views/view.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource views // diff --git a/api/gen/status/client.go b/api/gen/status/client.go index d4ca1edb03..62c752c9a9 100644 --- a/api/gen/status/client.go +++ b/api/gen/status/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // status client // diff --git a/api/gen/status/endpoints.go b/api/gen/status/endpoints.go index 26479b0f82..ab3a2f75cb 100644 --- a/api/gen/status/endpoints.go +++ b/api/gen/status/endpoints.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // status endpoints // diff --git a/api/gen/status/service.go b/api/gen/status/service.go index 56e7a2cfeb..37f9b4fc42 100644 --- a/api/gen/status/service.go +++ b/api/gen/status/service.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // status service // diff --git a/api/gen/swagger/client.go b/api/gen/swagger/client.go index efef781779..dcc6d00331 100644 --- a/api/gen/swagger/client.go +++ b/api/gen/swagger/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // swagger client // diff --git a/api/gen/swagger/endpoints.go b/api/gen/swagger/endpoints.go index f95846d792..9388993b4b 100644 --- a/api/gen/swagger/endpoints.go +++ b/api/gen/swagger/endpoints.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // swagger endpoints // diff --git a/api/gen/swagger/service.go b/api/gen/swagger/service.go index 37141df3c1..75efa8e1e3 100644 --- a/api/gen/swagger/service.go +++ b/api/gen/swagger/service.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // swagger service // diff --git a/api/v1/gen/catalog/client.go b/api/v1/gen/catalog/client.go index 242f85e72f..076b356442 100644 --- a/api/v1/gen/catalog/client.go +++ b/api/v1/gen/catalog/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog client // diff --git a/api/v1/gen/catalog/endpoints.go b/api/v1/gen/catalog/endpoints.go index f3f491f436..590f4b53a3 100644 --- a/api/v1/gen/catalog/endpoints.go +++ b/api/v1/gen/catalog/endpoints.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog endpoints // diff --git a/api/v1/gen/catalog/service.go b/api/v1/gen/catalog/service.go index d001e8b557..13af9d2d6d 100644 --- a/api/v1/gen/catalog/service.go +++ b/api/v1/gen/catalog/service.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog service // diff --git a/api/v1/gen/catalog/views/view.go b/api/v1/gen/catalog/views/view.go index e017792cb2..ba9df2b29a 100644 --- a/api/v1/gen/catalog/views/view.go +++ b/api/v1/gen/catalog/views/view.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog views // diff --git a/api/v1/gen/http/catalog/client/cli.go b/api/v1/gen/http/catalog/client/cli.go index e1764f0afb..efc43b8e7e 100644 --- a/api/v1/gen/http/catalog/client/cli.go +++ b/api/v1/gen/http/catalog/client/cli.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog HTTP client CLI support package // diff --git a/api/v1/gen/http/catalog/client/client.go b/api/v1/gen/http/catalog/client/client.go index 81e03f6f71..231b55ba91 100644 --- a/api/v1/gen/http/catalog/client/client.go +++ b/api/v1/gen/http/catalog/client/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog client HTTP transport // diff --git a/api/v1/gen/http/catalog/client/encode_decode.go b/api/v1/gen/http/catalog/client/encode_decode.go index 37a877713e..d493e852de 100644 --- a/api/v1/gen/http/catalog/client/encode_decode.go +++ b/api/v1/gen/http/catalog/client/encode_decode.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog HTTP client encoders and decoders // diff --git a/api/v1/gen/http/catalog/client/paths.go b/api/v1/gen/http/catalog/client/paths.go index dcbfd2eca4..22b9427e07 100644 --- a/api/v1/gen/http/catalog/client/paths.go +++ b/api/v1/gen/http/catalog/client/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the catalog service. // diff --git a/api/v1/gen/http/catalog/client/types.go b/api/v1/gen/http/catalog/client/types.go index ea06713e82..c32b51e029 100644 --- a/api/v1/gen/http/catalog/client/types.go +++ b/api/v1/gen/http/catalog/client/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog HTTP client types // diff --git a/api/v1/gen/http/catalog/server/encode_decode.go b/api/v1/gen/http/catalog/server/encode_decode.go index 3f38e230ce..9b1953fdfc 100644 --- a/api/v1/gen/http/catalog/server/encode_decode.go +++ b/api/v1/gen/http/catalog/server/encode_decode.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog HTTP server encoders and decoders // diff --git a/api/v1/gen/http/catalog/server/paths.go b/api/v1/gen/http/catalog/server/paths.go index 88a29ed6fe..6e2145f724 100644 --- a/api/v1/gen/http/catalog/server/paths.go +++ b/api/v1/gen/http/catalog/server/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the catalog service. // diff --git a/api/v1/gen/http/catalog/server/server.go b/api/v1/gen/http/catalog/server/server.go index 7b1d17c7fb..5ef6228369 100644 --- a/api/v1/gen/http/catalog/server/server.go +++ b/api/v1/gen/http/catalog/server/server.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog HTTP server // diff --git a/api/v1/gen/http/catalog/server/types.go b/api/v1/gen/http/catalog/server/types.go index 40b4f29992..8c345c5cd2 100644 --- a/api/v1/gen/http/catalog/server/types.go +++ b/api/v1/gen/http/catalog/server/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // catalog HTTP server types // diff --git a/api/v1/gen/http/cli/hub/cli.go b/api/v1/gen/http/cli/hub/cli.go index beedd6349b..6c490df27d 100644 --- a/api/v1/gen/http/cli/hub/cli.go +++ b/api/v1/gen/http/cli/hub/cli.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // hub HTTP client CLI support package // diff --git a/api/v1/gen/http/resource/client/cli.go b/api/v1/gen/http/resource/client/cli.go index adb2802738..47cc13f62f 100644 --- a/api/v1/gen/http/resource/client/cli.go +++ b/api/v1/gen/http/resource/client/cli.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource HTTP client CLI support package // diff --git a/api/v1/gen/http/resource/client/client.go b/api/v1/gen/http/resource/client/client.go index 4d9b4ef414..d55edfff78 100644 --- a/api/v1/gen/http/resource/client/client.go +++ b/api/v1/gen/http/resource/client/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource client HTTP transport // diff --git a/api/v1/gen/http/resource/client/encode_decode.go b/api/v1/gen/http/resource/client/encode_decode.go index 8687a34a2f..0a1c99aaee 100644 --- a/api/v1/gen/http/resource/client/encode_decode.go +++ b/api/v1/gen/http/resource/client/encode_decode.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource HTTP client encoders and decoders // diff --git a/api/v1/gen/http/resource/client/paths.go b/api/v1/gen/http/resource/client/paths.go index ee76ef86d2..21f53af19e 100644 --- a/api/v1/gen/http/resource/client/paths.go +++ b/api/v1/gen/http/resource/client/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the resource service. // diff --git a/api/v1/gen/http/resource/client/types.go b/api/v1/gen/http/resource/client/types.go index 4403168f1f..f7318f64c1 100644 --- a/api/v1/gen/http/resource/client/types.go +++ b/api/v1/gen/http/resource/client/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource HTTP client types // diff --git a/api/v1/gen/http/resource/server/encode_decode.go b/api/v1/gen/http/resource/server/encode_decode.go index 74e070886c..d6dbf984da 100644 --- a/api/v1/gen/http/resource/server/encode_decode.go +++ b/api/v1/gen/http/resource/server/encode_decode.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource HTTP server encoders and decoders // diff --git a/api/v1/gen/http/resource/server/paths.go b/api/v1/gen/http/resource/server/paths.go index b89320afe1..7ecc560c1f 100644 --- a/api/v1/gen/http/resource/server/paths.go +++ b/api/v1/gen/http/resource/server/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the resource service. // diff --git a/api/v1/gen/http/resource/server/server.go b/api/v1/gen/http/resource/server/server.go index b9c43b279b..2abc3cf4c0 100644 --- a/api/v1/gen/http/resource/server/server.go +++ b/api/v1/gen/http/resource/server/server.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource HTTP server // diff --git a/api/v1/gen/http/resource/server/types.go b/api/v1/gen/http/resource/server/types.go index 981d2c2d98..cf1122ca58 100644 --- a/api/v1/gen/http/resource/server/types.go +++ b/api/v1/gen/http/resource/server/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource HTTP server types // diff --git a/api/v1/gen/http/swagger/client/client.go b/api/v1/gen/http/swagger/client/client.go index a9deef2dfe..5c4f13d6b3 100644 --- a/api/v1/gen/http/swagger/client/client.go +++ b/api/v1/gen/http/swagger/client/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // swagger client HTTP transport // diff --git a/api/v1/gen/http/swagger/client/encode_decode.go b/api/v1/gen/http/swagger/client/encode_decode.go index c03ecfa724..f54b0835b3 100644 --- a/api/v1/gen/http/swagger/client/encode_decode.go +++ b/api/v1/gen/http/swagger/client/encode_decode.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // swagger HTTP client encoders and decoders // diff --git a/api/v1/gen/http/swagger/client/paths.go b/api/v1/gen/http/swagger/client/paths.go index 2c18010fee..e6c6cb5608 100644 --- a/api/v1/gen/http/swagger/client/paths.go +++ b/api/v1/gen/http/swagger/client/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the swagger service. // diff --git a/api/v1/gen/http/swagger/client/types.go b/api/v1/gen/http/swagger/client/types.go index 6751aff3a6..3694c1d856 100644 --- a/api/v1/gen/http/swagger/client/types.go +++ b/api/v1/gen/http/swagger/client/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // swagger HTTP client types // diff --git a/api/v1/gen/http/swagger/server/paths.go b/api/v1/gen/http/swagger/server/paths.go index d8b96ffb55..0259499a8a 100644 --- a/api/v1/gen/http/swagger/server/paths.go +++ b/api/v1/gen/http/swagger/server/paths.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // HTTP request path constructors for the swagger service. // diff --git a/api/v1/gen/http/swagger/server/server.go b/api/v1/gen/http/swagger/server/server.go index 41c402fd62..18458a5f06 100644 --- a/api/v1/gen/http/swagger/server/server.go +++ b/api/v1/gen/http/swagger/server/server.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // swagger HTTP server // diff --git a/api/v1/gen/http/swagger/server/types.go b/api/v1/gen/http/swagger/server/types.go index 955b58618a..4d38696f3a 100644 --- a/api/v1/gen/http/swagger/server/types.go +++ b/api/v1/gen/http/swagger/server/types.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // swagger HTTP server types // diff --git a/api/v1/gen/resource/client.go b/api/v1/gen/resource/client.go index bf1fa9cd70..b7df3f8f96 100644 --- a/api/v1/gen/resource/client.go +++ b/api/v1/gen/resource/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource client // diff --git a/api/v1/gen/resource/endpoints.go b/api/v1/gen/resource/endpoints.go index 51b724623f..3639e1c1c6 100644 --- a/api/v1/gen/resource/endpoints.go +++ b/api/v1/gen/resource/endpoints.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource endpoints // diff --git a/api/v1/gen/resource/service.go b/api/v1/gen/resource/service.go index 6cccfd87b1..441d6b1b55 100644 --- a/api/v1/gen/resource/service.go +++ b/api/v1/gen/resource/service.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource service // diff --git a/api/v1/gen/resource/views/view.go b/api/v1/gen/resource/views/view.go index 8f53604112..2715e7d633 100644 --- a/api/v1/gen/resource/views/view.go +++ b/api/v1/gen/resource/views/view.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // resource views // diff --git a/api/v1/gen/swagger/client.go b/api/v1/gen/swagger/client.go index 54d03f4432..2334f4c41f 100644 --- a/api/v1/gen/swagger/client.go +++ b/api/v1/gen/swagger/client.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // swagger client // diff --git a/api/v1/gen/swagger/endpoints.go b/api/v1/gen/swagger/endpoints.go index cf50656b81..79092ba5d5 100644 --- a/api/v1/gen/swagger/endpoints.go +++ b/api/v1/gen/swagger/endpoints.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // swagger endpoints // diff --git a/api/v1/gen/swagger/service.go b/api/v1/gen/swagger/service.go index 66f14bbf1c..f7bc906740 100644 --- a/api/v1/gen/swagger/service.go +++ b/api/v1/gen/swagger/service.go @@ -1,4 +1,4 @@ -// Code generated by goa v3.19.1, DO NOT EDIT. +// Code generated by goa v3.20.0, DO NOT EDIT. // // swagger service // diff --git a/go.mod b/go.mod index 47c7e9a0b4..6a73f48926 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/tektoncd/hub -go 1.22.3 +go 1.23.0 -toolchain go1.22.9 +toolchain go1.23.7 require ( github.com/ActiveState/vt10x v1.3.1 @@ -28,8 +28,8 @@ require ( github.com/tektoncd/plumbing v0.0.0-20220817140952-3da8ce01aeeb go.uber.org/automaxprocs v1.6.0 go.uber.org/zap v1.27.0 - goa.design/goa/v3 v3.19.1 - goa.design/plugins/v3 v3.19.1 + goa.design/goa/v3 v3.20.0 + goa.design/plugins/v3 v3.20.0 golang.org/x/term v0.29.0 golang.org/x/text v0.22.0 gopkg.in/h2non/gock.v1 v1.1.2 @@ -77,7 +77,7 @@ require ( github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-chi/chi/v5 v5.1.0 // indirect + github.com/go-chi/chi/v5 v5.2.1 // indirect github.com/go-jose/go-jose/v4 v4.0.5 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect @@ -87,6 +87,7 @@ require ( github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/gohugoio/hashstructure v0.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/cel-go v0.23.1 // indirect @@ -174,22 +175,22 @@ require ( go.opentelemetry.io/otel/trace v1.34.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.32.0 // indirect + golang.org/x/crypto v0.33.0 // indirect golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/net v0.34.0 // indirect + golang.org/x/mod v0.23.0 // indirect + golang.org/x/net v0.35.0 // indirect golang.org/x/oauth2 v0.25.0 // indirect golang.org/x/sync v0.11.0 // indirect golang.org/x/sys v0.30.0 // indirect golang.org/x/time v0.8.0 // indirect - golang.org/x/tools v0.25.0 // indirect + golang.org/x/tools v0.30.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/api v0.214.0 // indirect google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250219182151-9fdb1cabc7b2 // indirect google.golang.org/grpc v1.70.0 // indirect - google.golang.org/protobuf v1.36.4 // indirect + google.golang.org/protobuf v1.36.5 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 0d26adea0e..e84e44105a 100644 --- a/go.sum +++ b/go.sum @@ -1060,13 +1060,13 @@ github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXt github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/gdamore/encoding v0.0.0-20151215212835-b23993cbb635/go.mod h1:yrQYJKKDTrHmbYxI7CYi+/hbdiDT2m4Hj+t0ikCjsrQ= github.com/gdamore/tcell v1.0.1-0.20180608172421-b3cebc399d6f/go.mod h1:tqyG50u7+Ctv1w5VX67kLzKcj9YXR/JSBZQq/+mLl1A= -github.com/getkin/kin-openapi v0.127.0 h1:Mghqi3Dhryf3F8vR370nN67pAERW+3a95vomb3MAREY= -github.com/getkin/kin-openapi v0.127.0/go.mod h1:OZrfXzUfGrNbsKj+xmFBx6E5c6yH3At/tAKSc2UszXM= +github.com/getkin/kin-openapi v0.129.0 h1:QGYTNcmyP5X0AtFQ2Dkou9DGBJsUETeLH9rFrJXZh30= +github.com/getkin/kin-openapi v0.129.0/go.mod h1:gmWI+b/J45xqpyK5wJmRRZse5wefA5H0RDMK46kLUtI= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= -github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8= +github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0= github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY= github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw= @@ -1160,6 +1160,8 @@ github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/gohugoio/hashstructure v0.5.0 h1:G2fjSBU36RdwEJBWJ+919ERvOVqAg9tfcYp47K9swqg= +github.com/gohugoio/hashstructure v0.5.0/go.mod h1:Ser0TniXuu/eauYmrwM4o64EBvySxNzITEOLlm4igec= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= @@ -1405,8 +1407,6 @@ github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso= -github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA= github.com/itchyny/gojq v0.12.16 h1:yLfgLxhIr/6sJNVmYfQjTIv0jGctu6/DgDoivmxTr7g= github.com/itchyny/gojq v0.12.16/go.mod h1:6abHbdC2uB9ogMS38XsErnfqJ94UlngIJGlRAIj4jTM= github.com/itchyny/timefmt-go v0.1.6 h1:ia3s54iciXDdzWzwaVKXZPbiXzxxnv1SPGFfM/myJ5Q= @@ -1604,6 +1604,10 @@ github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uY github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80 h1:nZspmSkneBbtxU9TopEAE0CY+SBJLxO8LPUlw2vG4pU= +github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80/go.mod h1:7tFDb+Y51LcDpn26GccuUgQXUk6t0CXZsivKjyimYX8= +github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349 h1:t05Ww3DxZutOqbMN+7OIuqDwXbhl32HiZGpLy26BAPc= +github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -1996,10 +2000,10 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -goa.design/goa/v3 v3.19.1 h1:jpV3LEy7YANzPMwm++Lu17RoThRJgXrPxdEM0A1nlOE= -goa.design/goa/v3 v3.19.1/go.mod h1:astNE9ube0YCxqq7DQkt1MtLxB/b3kRPEFkEZovcO2I= -goa.design/plugins/v3 v3.19.1 h1:PT/PqzymVohIzq6l8I4qYRSB2RCBMIFJ7QqnkA1kblQ= -goa.design/plugins/v3 v3.19.1/go.mod h1:IjmiAqbpTowpBXDyNboLaGdOZMlclb99dGE4f8qalVs= +goa.design/goa/v3 v3.20.0 h1:mYYNqCBg9SSxe2jxvPJFOPmJqqKkSAUSU84jpczky3s= +goa.design/goa/v3 v3.20.0/go.mod h1:g8sT4ioTaRt8BZKwZ1YOQe7UgWqkZMx+q6NWgQfzLUU= +goa.design/plugins/v3 v3.20.0 h1:1PaevrRloUS6Dd/BsvwmdQmrlStzf1vX7KMhLKQut6E= +goa.design/plugins/v3 v3.20.0/go.mod h1:LMbmQVgSeGerokWyTcKqsVRSkLrfzVlBSNLa6i9XZTg= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -2021,8 +2025,8 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -2082,8 +2086,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2157,8 +2161,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -2447,8 +2451,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE= -golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2677,8 +2681,8 @@ google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA= google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250219182151-9fdb1cabc7b2 h1:DMTIbak9GhdaSxEjvVzAeNZvyc03I61duqNbnm3SU0M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250219182151-9fdb1cabc7b2/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -2744,8 +2748,8 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= -google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0/go.mod h1:OdE7CF6DbADk7lN8LIKRzRJTTZXIjtWgA5THM5lhBAw= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= diff --git a/test/presubmit-tests.sh b/test/presubmit-tests.sh index 23ae780104..484c21441f 100755 --- a/test/presubmit-tests.sh +++ b/test/presubmit-tests.sh @@ -131,7 +131,7 @@ goa-gen() { go version export GOFLAGS="" - go install goa.design/goa/v3/cmd/goa@v3.19.1 + go install goa.design/goa/v3/cmd/goa@v3.20.0 goa version diff --git a/vendor/github.com/go-chi/chi/v5/README.md b/vendor/github.com/go-chi/chi/v5/README.md index 21cbb0fc0a..7f662ab45f 100644 --- a/vendor/github.com/go-chi/chi/v5/README.md +++ b/vendor/github.com/go-chi/chi/v5/README.md @@ -65,7 +65,7 @@ func main() { **REST Preview:** -Here is a little preview of how routing looks like with chi. Also take a look at the generated routing docs +Here is a little preview of what routing looks like with chi. Also take a look at the generated routing docs in JSON ([routes.json](https://github.com/go-chi/chi/blob/master/_examples/rest/routes.json)) and in Markdown ([routes.md](https://github.com/go-chi/chi/blob/master/_examples/rest/routes.md)). @@ -469,7 +469,8 @@ how setting context on a request in Go works. * Carl Jackson for https://github.com/zenazn/goji * Parts of chi's thinking comes from goji, and chi's middleware package - sources from goji. + sources from [goji](https://github.com/zenazn/goji/tree/master/web/middleware). + * Please see goji's [LICENSE](https://github.com/zenazn/goji/blob/master/LICENSE) (MIT) * Armon Dadgar for https://github.com/armon/go-radix * Contributions: [@VojtechVitek](https://github.com/VojtechVitek) diff --git a/vendor/github.com/go-chi/chi/v5/chi.go b/vendor/github.com/go-chi/chi/v5/chi.go index a1691bbeb1..fc32c4efe9 100644 --- a/vendor/github.com/go-chi/chi/v5/chi.go +++ b/vendor/github.com/go-chi/chi/v5/chi.go @@ -51,7 +51,7 @@ // "/user/{name}" matches "/user/jsmith" but not "/user/jsmith/info" or "/user/jsmith/" // "/user/{name}/info" matches "/user/jsmith/info" // "/page/*" matches "/page/intro/latest" -// "/page/{other}/index" also matches "/page/intro/latest" +// "/page/{other}/latest" also matches "/page/intro/latest" // "/date/{yyyy:\\d\\d\\d\\d}/{mm:\\d\\d}/{dd:\\d\\d}" matches "/date/2017/04/01" package chi @@ -127,6 +127,10 @@ type Routes interface { // the method/path - similar to routing a http request, but without // executing the handler thereafter. Match(rctx *Context, method, path string) bool + + // Find searches the routing tree for the pattern that matches + // the method/path. + Find(rctx *Context, method, path string) string } // Middlewares type is a slice of standard middleware handlers with methods diff --git a/vendor/github.com/go-chi/chi/v5/context.go b/vendor/github.com/go-chi/chi/v5/context.go index e2cd908d72..aacf6eff72 100644 --- a/vendor/github.com/go-chi/chi/v5/context.go +++ b/vendor/github.com/go-chi/chi/v5/context.go @@ -109,7 +109,7 @@ func (x *Context) URLParam(key string) string { // RoutePattern builds the routing pattern string for the particular // request, at the particular point during routing. This means, the value // will change throughout the execution of a request in a router. That is -// why its advised to only use this value after calling the next handler. +// why it's advised to only use this value after calling the next handler. // // For example, // @@ -121,6 +121,9 @@ func (x *Context) URLParam(key string) string { // }) // } func (x *Context) RoutePattern() string { + if x == nil { + return "" + } routePattern := strings.Join(x.RoutePatterns, "") routePattern = replaceWildcards(routePattern) if routePattern != "/" { diff --git a/vendor/github.com/go-chi/chi/v5/mux.go b/vendor/github.com/go-chi/chi/v5/mux.go index 6dc1904d9b..91daf691e9 100644 --- a/vendor/github.com/go-chi/chi/v5/mux.go +++ b/vendor/github.com/go-chi/chi/v5/mux.go @@ -363,19 +363,40 @@ func (mx *Mux) Middlewares() Middlewares { // Note: the *Context state is updated during execution, so manage // the state carefully or make a NewRouteContext(). func (mx *Mux) Match(rctx *Context, method, path string) bool { + return mx.Find(rctx, method, path) != "" +} + +// Find searches the routing tree for the pattern that matches +// the method/path. +// +// Note: the *Context state is updated during execution, so manage +// the state carefully or make a NewRouteContext(). +func (mx *Mux) Find(rctx *Context, method, path string) string { m, ok := methodMap[method] if !ok { - return false + return "" } - node, _, h := mx.tree.FindRoute(rctx, m, path) + node, _, _ := mx.tree.FindRoute(rctx, m, path) + pattern := rctx.routePattern + + if node != nil { + if node.subroutes == nil { + e := node.endpoints[m] + return e.pattern + } - if node != nil && node.subroutes != nil { rctx.RoutePath = mx.nextRoutePath(rctx) - return node.subroutes.Match(rctx, method, rctx.RoutePath) + subPattern := node.subroutes.Find(rctx, method, rctx.RoutePath) + if subPattern == "" { + return "" + } + + pattern = strings.TrimSuffix(pattern, "/*") + pattern += subPattern } - return h != nil + return pattern } // NotFoundHandler returns the default Mux 404 responder whenever a route diff --git a/vendor/github.com/gohugoio/hashstructure/.gitignore b/vendor/github.com/gohugoio/hashstructure/.gitignore new file mode 100644 index 0000000000..c56069fe26 --- /dev/null +++ b/vendor/github.com/gohugoio/hashstructure/.gitignore @@ -0,0 +1 @@ +*.test \ No newline at end of file diff --git a/vendor/github.com/gohugoio/hashstructure/LICENSE b/vendor/github.com/gohugoio/hashstructure/LICENSE new file mode 100644 index 0000000000..a3866a291f --- /dev/null +++ b/vendor/github.com/gohugoio/hashstructure/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/gohugoio/hashstructure/README.md b/vendor/github.com/gohugoio/hashstructure/README.md new file mode 100644 index 0000000000..054586a80b --- /dev/null +++ b/vendor/github.com/gohugoio/hashstructure/README.md @@ -0,0 +1,67 @@ +# hashstructure [![GoDoc](https://godoc.org/github.com/mitchellh/hashstructure?status.svg)](https://godoc.org/github.com/mitchellh/hashstructure) + +hashstructure is a Go library for creating a unique hash value +for arbitrary values in Go. + +This can be used to key values in a hash (for use in a map, set, etc.) +that are complex. The most common use case is comparing two values without +sending data across the network, caching values locally (de-dup), and so on. + +## Features + + * Hash any arbitrary Go value, including complex types. + + * Tag a struct field to ignore it and not affect the hash value. + + * Tag a slice type struct field to treat it as a set where ordering + doesn't affect the hash code but the field itself is still taken into + account to create the hash value. + + * Optionally, specify a custom hash function to optimize for speed, collision + avoidance for your data set, etc. + + * Optionally, hash the output of `.String()` on structs that implement fmt.Stringer, + allowing effective hashing of time.Time + + * Optionally, override the hashing process by implementing `Hashable`. + +## Installation + +Standard `go get`: + +``` +$ go get github.com/gohugoio/hashstructure +``` + +## Usage & Example + +For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/hashstructure). + +A quick code example is shown below: + +```go +type ComplexStruct struct { + Name string + Age uint + Metadata map[string]interface{} +} + +v := ComplexStruct{ + Name: "mitchellh", + Age: 64, + Metadata: map[string]interface{}{ + "car": true, + "location": "California", + "siblings": []string{"Bob", "John"}, + }, +} + +hash, err := hashstructure.Hash(v, nil) +if err != nil { + panic(err) +} + +fmt.Printf("%d", hash) +// Output: +// 2307517237273902113 +``` diff --git a/vendor/github.com/gohugoio/hashstructure/errors.go b/vendor/github.com/gohugoio/hashstructure/errors.go new file mode 100644 index 0000000000..44b8951478 --- /dev/null +++ b/vendor/github.com/gohugoio/hashstructure/errors.go @@ -0,0 +1,22 @@ +package hashstructure + +import ( + "fmt" +) + +// ErrNotStringer is returned when there's an error with hash:"string" +type ErrNotStringer struct { + Field string +} + +// Error implements error for ErrNotStringer +func (ens *ErrNotStringer) Error() string { + return fmt.Sprintf("hashstructure: %s has hash:\"string\" set, but does not implement fmt.Stringer", ens.Field) +} + +// ErrFormat is returned when an invalid format is given to the Hash function. +type ErrFormat struct{} + +func (*ErrFormat) Error() string { + return "format must be one of the defined Format values in the hashstructure library" +} diff --git a/vendor/github.com/gohugoio/hashstructure/hashstructure.go b/vendor/github.com/gohugoio/hashstructure/hashstructure.go new file mode 100644 index 0000000000..845be7dfdf --- /dev/null +++ b/vendor/github.com/gohugoio/hashstructure/hashstructure.go @@ -0,0 +1,488 @@ +package hashstructure + +import ( + "encoding/binary" + "fmt" + "hash" + "hash/fnv" + "io" + "reflect" + "time" +) + +// HashOptions are options that are available for hashing. +type HashOptions struct { + // Hasher is the hash function to use. If this isn't set, it will + // default to FNV. + Hasher hash.Hash64 + + // TagName is the struct tag to look at when hashing the structure. + // By default this is "hash". + TagName string + + // ZeroNil is flag determining if nil pointer should be treated equal + // to a zero value of pointed type. By default this is false. + ZeroNil bool + + // IgnoreZeroValue is determining if zero value fields should be + // ignored for hash calculation. + IgnoreZeroValue bool + + // SlicesAsSets assumes that a `set` tag is always present for slices. + // Default is false (in which case the tag is used instead) + SlicesAsSets bool + + // UseStringer will attempt to use fmt.Stringer always. If the struct + // doesn't implement fmt.Stringer, it'll fall back to trying usual tricks. + // If this is true, and the "string" tag is also set, the tag takes + // precedence (meaning that if the type doesn't implement fmt.Stringer, we + // panic) + UseStringer bool +} + +// Hash returns the hash value of an arbitrary value. +// +// If opts is nil, then default options will be used. See HashOptions +// for the default values. The same *HashOptions value cannot be used +// concurrently. None of the values within a *HashOptions struct are +// safe to read/write while hashing is being done. +// +// The "format" is required and must be one of the format values defined +// by this library. You should probably just use "FormatV2". This allows +// generated hashes uses alternate logic to maintain compatibility with +// older versions. +// +// Notes on the value: +// +// - Unexported fields on structs are ignored and do not affect the +// hash value. +// +// - Adding an exported field to a struct with the zero value will change +// the hash value. +// +// For structs, the hashing can be controlled using tags. For example: +// +// struct { +// Name string +// UUID string `hash:"ignore"` +// } +// +// The available tag values are: +// +// - "ignore" or "-" - The field will be ignored and not affect the hash code. +// +// - "set" - The field will be treated as a set, where ordering doesn't +// affect the hash code. This only works for slices. +// +// - "string" - The field will be hashed as a string, only works when the +// field implements fmt.Stringer +func Hash(v interface{}, opts *HashOptions) (uint64, error) { + // Create default options + if opts == nil { + opts = &HashOptions{} + } + if opts.Hasher == nil { + opts.Hasher = fnv.New64() + } + if opts.TagName == "" { + opts.TagName = "hash" + } + + // Reset the hash + opts.Hasher.Reset() + + // Fast path for strings. + if s, ok := v.(string); ok { + return hashString(opts.Hasher, s) + } + + // Create our walker and walk the structure + w := &walker{ + h: opts.Hasher, + tag: opts.TagName, + zeronil: opts.ZeroNil, + ignorezerovalue: opts.IgnoreZeroValue, + sets: opts.SlicesAsSets, + stringer: opts.UseStringer, + } + return w.visit(reflect.ValueOf(v), nil) +} + +type walker struct { + h hash.Hash64 + tag string + zeronil bool + ignorezerovalue bool + sets bool + stringer bool +} + +type visitOpts struct { + // Flags are a bitmask of flags to affect behavior of this visit + Flags visitFlag + + // Information about the struct containing this field + Struct interface{} + StructField string +} + +var timeType = reflect.TypeOf(time.Time{}) + +// A direct hash calculation used for numeric and bool values. +func (w *walker) hashDirect(v any) (uint64, error) { + w.h.Reset() + err := binary.Write(w.h, binary.LittleEndian, v) + return w.h.Sum64(), err +} + +// A direct hash calculation used for strings. +func (w *walker) hashString(s string) (uint64, error) { + return hashString(w.h, s) +} + +// A direct hash calculation used for strings. +func hashString(h hash.Hash64, s string) (uint64, error) { + h.Reset() + + // io.WriteString uses io.StringWriter if it exists, which is + // implemented by e.g. github.com/cespare/xxhash. + _, err := io.WriteString(h, s) + return h.Sum64(), err +} + +func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) { + t := reflect.TypeOf(0) + + // Loop since these can be wrapped in multiple layers of pointers + // and interfaces. + for { + // If we have an interface, dereference it. We have to do this up + // here because it might be a nil in there and the check below must + // catch that. + if v.Kind() == reflect.Interface { + v = v.Elem() + continue + } + + if v.Kind() == reflect.Ptr { + if w.zeronil { + t = v.Type().Elem() + } + v = reflect.Indirect(v) + continue + } + + break + } + + // If it is nil, treat it like a zero. + if !v.IsValid() { + v = reflect.Zero(t) + } + + if v.CanInt() { + if v.Kind() == reflect.Int { + // binary.Write requires a fixed-size value. + return w.hashDirect(v.Int()) + } + return w.hashDirect(v.Interface()) + } + + if v.CanUint() { + if v.Kind() == reflect.Uint { + // binary.Write requires a fixed-size value. + return w.hashDirect(v.Uint()) + } + return w.hashDirect(v.Interface()) + } + + if v.CanFloat() || v.CanComplex() { + return w.hashDirect(v.Interface()) + } + + k := v.Kind() + + if k == reflect.Bool { + var tmp int8 + if v.Bool() { + tmp = 1 + } + return w.hashDirect(tmp) + } + + switch v.Type() { + case timeType: + w.h.Reset() + b, err := v.Interface().(time.Time).MarshalBinary() + if err != nil { + return 0, err + } + + err = binary.Write(w.h, binary.LittleEndian, b) + return w.h.Sum64(), err + } + + switch k { + case reflect.Array: + var h uint64 + l := v.Len() + for i := 0; i < l; i++ { + current, err := w.visit(v.Index(i), nil) + if err != nil { + return 0, err + } + + h = hashUpdateOrdered(w.h, h, current) + } + + return h, nil + + case reflect.Map: + var includeMap IncludableMap + var field string + + if v, ok := v.Interface().(IncludableMap); ok { + includeMap = v + } else if opts != nil && opts.Struct != nil { + if v, ok := opts.Struct.(IncludableMap); ok { + includeMap, field = v, opts.StructField + } + } + + // Build the hash for the map. We do this by XOR-ing all the key + // and value hashes. This makes it deterministic despite ordering. + var h uint64 + + k := reflect.New(v.Type().Key()).Elem() + vv := reflect.New(v.Type().Elem()).Elem() + + iter := v.MapRange() + + for iter.Next() { + k.SetIterKey(iter) + vv.SetIterValue(iter) + if includeMap != nil { + incl, err := includeMap.HashIncludeMap(field, k.Interface(), vv.Interface()) + if err != nil { + return 0, err + } + if !incl { + continue + } + } + + kh, err := w.visit(k, nil) + if err != nil { + return 0, err + } + vh, err := w.visit(vv, nil) + if err != nil { + return 0, err + } + + fieldHash := hashUpdateOrdered(w.h, kh, vh) + h = hashUpdateUnordered(h, fieldHash) + } + + // Important: read the docs for hashFinishUnordered + h = hashFinishUnordered(w.h, h) + + return h, nil + + case reflect.Struct: + parent := v.Interface() + var include Includable + if impl, ok := parent.(Includable); ok { + include = impl + } + + if impl, ok := parent.(Hashable); ok { + return impl.Hash() + } + + // If we can address this value, check if the pointer value + // implements our interfaces and use that if so. + if v.CanAddr() { + vptr := v.Addr() + parentptr := vptr.Interface() + if impl, ok := parentptr.(Includable); ok { + include = impl + } + + if impl, ok := parentptr.(Hashable); ok { + return impl.Hash() + } + } + + t := v.Type() + h, err := w.visit(reflect.ValueOf(t.Name()), nil) + if err != nil { + return 0, err + } + + l := v.NumField() + for i := 0; i < l; i++ { + if innerV := v.Field(i); v.CanSet() || t.Field(i).Name != "_" { + var f visitFlag + fieldType := t.Field(i) + if fieldType.PkgPath != "" { + // Unexported + continue + } + + tag := fieldType.Tag.Get(w.tag) + if tag == "ignore" || tag == "-" { + // Ignore this field + continue + } + + if w.ignorezerovalue { + if innerV.IsZero() { + continue + } + } + + // if string is set, use the string value + if tag == "string" || w.stringer { + if impl, ok := innerV.Interface().(fmt.Stringer); ok { + innerV = reflect.ValueOf(impl.String()) + } else if tag == "string" { + // We only show this error if the tag explicitly + // requests a stringer. + return 0, &ErrNotStringer{ + Field: v.Type().Field(i).Name, + } + } + } + + // Check if we implement includable and check it + if include != nil { + incl, err := include.HashInclude(fieldType.Name, innerV) + if err != nil { + return 0, err + } + if !incl { + continue + } + } + + switch tag { + case "set": + f |= visitFlagSet + } + + kh, err := w.visit(reflect.ValueOf(fieldType.Name), nil) + if err != nil { + return 0, err + } + + vh, err := w.visit(innerV, &visitOpts{ + Flags: f, + Struct: parent, + StructField: fieldType.Name, + }) + if err != nil { + return 0, err + } + + fieldHash := hashUpdateOrdered(w.h, kh, vh) + h = hashUpdateUnordered(h, fieldHash) + } + // Important: read the docs for hashFinishUnordered + h = hashFinishUnordered(w.h, h) + } + + return h, nil + + case reflect.Slice: + // We have two behaviors here. If it isn't a set, then we just + // visit all the elements. If it is a set, then we do a deterministic + // hash code. + var h uint64 + var set bool + if opts != nil { + set = (opts.Flags & visitFlagSet) != 0 + } + l := v.Len() + for i := 0; i < l; i++ { + current, err := w.visit(v.Index(i), nil) + if err != nil { + return 0, err + } + + if set || w.sets { + h = hashUpdateUnordered(h, current) + } else { + h = hashUpdateOrdered(w.h, h, current) + } + } + + if set { + // Important: read the docs for hashFinishUnordered + h = hashFinishUnordered(w.h, h) + } + + return h, nil + + case reflect.String: + return w.hashString(v.String()) + default: + return 0, fmt.Errorf("unknown kind to hash: %s", k) + } +} + +func hashUpdateOrdered(h hash.Hash64, a, b uint64) uint64 { + // For ordered updates, use a real hash function + h.Reset() + + // We just panic if the binary writes fail because we are writing + // an int64 which should never be fail-able. + e1 := binary.Write(h, binary.LittleEndian, a) + e2 := binary.Write(h, binary.LittleEndian, b) + if e1 != nil { + panic(e1) + } + if e2 != nil { + panic(e2) + } + + return h.Sum64() +} + +func hashUpdateUnordered(a, b uint64) uint64 { + return a ^ b +} + +// After mixing a group of unique hashes with hashUpdateUnordered, it's always +// necessary to call hashFinishUnordered. Why? Because hashUpdateUnordered +// is a simple XOR, and calling hashUpdateUnordered on hashes produced by +// hashUpdateUnordered can effectively cancel out a previous change to the hash +// result if the same hash value appears later on. For example, consider: +// +// hashUpdateUnordered(hashUpdateUnordered("A", "B"), hashUpdateUnordered("A", "C")) = +// H("A") ^ H("B")) ^ (H("A") ^ H("C")) = +// (H("A") ^ H("A")) ^ (H("B") ^ H(C)) = +// H(B) ^ H(C) = +// hashUpdateUnordered(hashUpdateUnordered("Z", "B"), hashUpdateUnordered("Z", "C")) +// +// hashFinishUnordered "hardens" the result, so that encountering partially +// overlapping input data later on in a different context won't cancel out. +func hashFinishUnordered(h hash.Hash64, a uint64) uint64 { + h.Reset() + + // We just panic if the writes fail + e1 := binary.Write(h, binary.LittleEndian, a) + if e1 != nil { + panic(e1) + } + + return h.Sum64() +} + +// visitFlag is used as a bitmask for affecting visit behavior +type visitFlag uint + +const ( + visitFlagInvalid visitFlag = iota + visitFlagSet = iota << 1 +) diff --git a/vendor/github.com/gohugoio/hashstructure/include.go b/vendor/github.com/gohugoio/hashstructure/include.go new file mode 100644 index 0000000000..702d35415d --- /dev/null +++ b/vendor/github.com/gohugoio/hashstructure/include.go @@ -0,0 +1,22 @@ +package hashstructure + +// Includable is an interface that can optionally be implemented by +// a struct. It will be called for each field in the struct to check whether +// it should be included in the hash. +type Includable interface { + HashInclude(field string, v interface{}) (bool, error) +} + +// IncludableMap is an interface that can optionally be implemented by +// a struct. It will be called when a map-type field is found to ask the +// struct if the map item should be included in the hash. +type IncludableMap interface { + HashIncludeMap(field string, k, v interface{}) (bool, error) +} + +// Hashable is an interface that can optionally be implemented by a struct +// to override the hash value. This value will override the hash value for +// the entire struct. Entries in the struct will not be hashed. +type Hashable interface { + Hash() (uint64, error) +} diff --git a/vendor/goa.design/goa/v3/codegen/cli/cli.go b/vendor/goa.design/goa/v3/codegen/cli/cli.go index a69f747036..affdbfccd4 100644 --- a/vendor/goa.design/goa/v3/codegen/cli/cli.go +++ b/vendor/goa.design/goa/v3/codegen/cli/cli.go @@ -34,6 +34,8 @@ type ( // PkgName is the service HTTP client package import name, // e.g. "storagec". PkgName string + // Interceptors contains the data for client interceptors if any. + Interceptors *InterceptorData } // SubcommandData contains the data needed to render a sub-command. @@ -56,6 +58,16 @@ type ( Conversion string // Example is a valid command invocation, starting with the command name. Example string + // Interceptors contains the data for client interceptors if any apply to the endpoint method. + Interceptors *InterceptorData + } + + // InterceptorData contains the data needed to generate interceptor code. + InterceptorData struct { + // VarName is the name of the interceptor variable. + VarName string + // PkgName is the package name containing the interceptor type. + PkgName string } // FlagData contains the data needed to render a command-line flag. @@ -151,61 +163,71 @@ func BuildCommandData(data *service.Data) *CommandData { if description == "" { description = fmt.Sprintf("Make requests to the %q service", data.Name) } + + var interceptors *InterceptorData + if len(data.ClientInterceptors) > 0 { + interceptors = &InterceptorData{ + VarName: "inter", + PkgName: data.PkgName, + } + } + return &CommandData{ - Name: codegen.KebabCase(data.Name), - VarName: codegen.Goify(data.Name, false), - Description: description, - PkgName: data.PkgName + "c", + Name: codegen.KebabCase(data.Name), + VarName: codegen.Goify(data.Name, false), + Description: description, + PkgName: data.PkgName + "c", + Interceptors: interceptors, } } // BuildSubcommandData builds the data needed by CLI code generators to render // the CLI parsing of the service sub-command. -func BuildSubcommandData(svcName string, m *service.MethodData, buildFunction *BuildFunctionData, flags []*FlagData) *SubcommandData { - var ( - name string - fullName string - description string - - conversion string - ) - { - en := m.Name - name = codegen.KebabCase(en) - fullName = goifyTerms(svcName, en) - description = m.Description - if description == "" { - description = fmt.Sprintf("Make request to the %q endpoint", m.Name) +func BuildSubcommandData(data *service.Data, m *service.MethodData, buildFunction *BuildFunctionData, flags []*FlagData) *SubcommandData { + en := m.Name + name := codegen.KebabCase(en) + fullName := goifyTerms(data.Name, en) + description := m.Description + if description == "" { + description = fmt.Sprintf("Make request to the %q endpoint", m.Name) + } + + var conversion string + if m.Payload != "" && buildFunction == nil && len(flags) > 0 { + // No build function, just convert the arg to the body type + var convPre, convSuff string + target := "data" + if flagType(m.Payload) == "JSON" { + target = "val" + convPre = fmt.Sprintf("var val %s\n", m.Payload) + convSuff = "\ndata = val" } - - if m.Payload != "" && buildFunction == nil && len(flags) > 0 { - // No build function, just convert the arg to the body type - var convPre, convSuff string - target := "data" + conv, _, check := conversionCode( + "*"+flags[0].FullName+"Flag", + target, + m.Payload, + false, + ) + conversion = convPre + conv + convSuff + if check { + conversion = "var err error\n" + conversion + conversion += "\nif err != nil {\n" if flagType(m.Payload) == "JSON" { - target = "val" - convPre = fmt.Sprintf("var val %s\n", m.Payload) - convSuff = "\ndata = val" - } - conv, _, check := conversionCode( - "*"+flags[0].FullName+"Flag", - target, - m.Payload, - false, - ) - conversion = convPre + conv + convSuff - if check { - conversion = "var err error\n" + conversion - conversion += "\nif err != nil {\n" - if flagType(m.Payload) == "JSON" { - conversion += fmt.Sprintf(`return nil, nil, fmt.Errorf("invalid JSON for %s, \nerror: %%s, \nexample of valid JSON:\n%%s", err, %q)`, - flags[0].FullName+"Flag", flags[0].Example) - } else { - conversion += fmt.Sprintf(`return nil, nil, fmt.Errorf("invalid value for %s, must be %s")`, - flags[0].FullName+"Flag", flags[0].Type) - } - conversion += "\n}" + conversion += fmt.Sprintf(`return nil, nil, fmt.Errorf("invalid JSON for %s, \nerror: %%s, \nexample of valid JSON:\n%%s", err, %q)`, + flags[0].FullName+"Flag", flags[0].Example) + } else { + conversion += fmt.Sprintf(`return nil, nil, fmt.Errorf("invalid value for %s, must be %s")`, + flags[0].FullName+"Flag", flags[0].Type) } + conversion += "\n}" + } + } + + var interceptors *InterceptorData + if len(m.ClientInterceptors) > 0 { + interceptors = &InterceptorData{ + VarName: "inter", + PkgName: data.PkgName, } } sub := &SubcommandData{ @@ -216,8 +238,9 @@ func BuildSubcommandData(svcName string, m *service.MethodData, buildFunction *B MethodVarName: m.VarName, BuildFunction: buildFunction, Conversion: conversion, + Interceptors: interceptors, } - generateExample(sub, svcName) + generateExample(sub, data.Name) return sub } @@ -333,66 +356,64 @@ func FieldLoadCode(f *FlagData, argName, argTypeName, validate string, defaultVa startIf string endIf string ) - { - if !f.Required { - startIf = fmt.Sprintf("if %s != \"\" {\n", f.FullName) - endIf = "\n}" - } - if argTypeName == codegen.GoNativeTypeName(expr.String) { - ref := "&" - if f.Required || defaultValue != nil { - ref = "" - } - code = argName + " = " + ref + f.FullName - declErr = validate != "" - } else { - var checkErr bool - code, declErr, checkErr = conversionCode(f.FullName, argName, argTypeName, !f.Required && defaultValue == nil) - if checkErr { - code += "\nif err != nil {\n" - nilVal := "nil" - if expr.IsPrimitive(payload) { - code += fmt.Sprintf("var zero %s\n", payloadRef) - nilVal = "zero" - } - if flagType(argTypeName) == "JSON" { - code += fmt.Sprintf(`return %s, fmt.Errorf("invalid JSON for %s, \nerror: %%s, \nexample of valid JSON:\n%%s", err, %q)`, - nilVal, argName, f.Example) - } else { - code += fmt.Sprintf(`return %s, fmt.Errorf("invalid value for %s, must be %s")`, - nilVal, argName, f.Type) - } - code += "\n}" - } + if !f.Required { + startIf = fmt.Sprintf("if %s != \"\" {\n", f.FullName) + endIf = "\n}" + } + if argTypeName == codegen.GoNativeTypeName(expr.String) { + ref := "&" + if f.Required || defaultValue != nil { + ref = "" } - if validate != "" { - nilCheck := "if " + argName + " != nil {" - if strings.HasPrefix(validate, nilCheck) { - // hackety hack... the validation code is generated for the client and needs to - // account for the fact that the field could be nil in this case. We are reusing - // that code to validate a CLI flag which can never be nil. Lint tools complain - // about that so remove the if statements. Ideally we'd have a better way to do - // this but that requires a lot of changes and the added complexity might not be - // worth it. - var lines []string - ls := strings.Split(validate, "\n") - for i := 1; i < len(ls)-1; i++ { - if ls[i+1] == nilCheck { - i++ // skip both closing brace on previous line and check - continue - } - lines = append(lines, ls[i]) - } - validate = strings.Join(lines, "\n") - } - code += "\n" + validate + "\n" + code = argName + " = " + ref + f.FullName + declErr = validate != "" + } else { + var checkErr bool + code, declErr, checkErr = conversionCode(f.FullName, argName, argTypeName, !f.Required && defaultValue == nil) + if checkErr { + code += "\nif err != nil {\n" nilVal := "nil" if expr.IsPrimitive(payload) { code += fmt.Sprintf("var zero %s\n", payloadRef) nilVal = "zero" } - code += fmt.Sprintf("if err != nil {\n\treturn %s, err\n}", nilVal) + if flagType(argTypeName) == "JSON" { + code += fmt.Sprintf(`return %s, fmt.Errorf("invalid JSON for %s, \nerror: %%s, \nexample of valid JSON:\n%%s", err, %q)`, + nilVal, argName, f.Example) + } else { + code += fmt.Sprintf(`return %s, fmt.Errorf("invalid value for %s, must be %s")`, + nilVal, argName, f.Type) + } + code += "\n}" + } + } + if validate != "" { + nilCheck := "if " + argName + " != nil {" + if strings.HasPrefix(validate, nilCheck) { + // hackety hack... the validation code is generated for the client and needs to + // account for the fact that the field could be nil in this case. We are reusing + // that code to validate a CLI flag which can never be nil. Lint tools complain + // about that so remove the if statements. Ideally we'd have a better way to do + // this but that requires a lot of changes and the added complexity might not be + // worth it. + var lines []string + ls := strings.Split(validate, "\n") + for i := 1; i < len(ls)-1; i++ { + if ls[i+1] == nilCheck { + i++ // skip both closing brace on previous line and check + continue + } + lines = append(lines, ls[i]) + } + validate = strings.Join(lines, "\n") + } + code += "\n" + validate + "\n" + nilVal := "nil" + if expr.IsPrimitive(payload) { + code += fmt.Sprintf("var zero %s\n", payloadRef) + nilVal = "zero" } + code += fmt.Sprintf("if err != nil {\n\treturn %s, err\n}", nilVal) } return fmt.Sprintf("%s%s%s", startIf, code, endIf), declErr } @@ -682,7 +703,8 @@ const parseFlagsT = `var ( ` // input: commandData -const commandUsageT = `{{ printf "%sUsage displays the usage of the %s command and its subcommands." .Name .Name | comment }} +const commandUsageT = ` +{{ printf "%sUsage displays the usage of the %s command and its subcommands." .VarName .Name | comment }} func {{ .VarName }}Usage() { fmt.Fprintf(os.Stderr, ` + "`" + `{{ printDescription .Description }} Usage: diff --git a/vendor/goa.design/goa/v3/codegen/example/example_server.go b/vendor/goa.design/goa/v3/codegen/example/example_server.go index f896106eb4..35576abf21 100644 --- a/vendor/goa.design/goa/v3/codegen/example/example_server.go +++ b/vendor/goa.design/goa/v3/codegen/example/example_server.go @@ -50,14 +50,17 @@ func exampleSvrMain(genpkg string, root *expr.RootExpr, svr *expr.ServerExpr) *c // Iterate through services listed in the server expression. svcData := make([]*service.Data, len(svr.Services)) scope := codegen.NewNameScope() + hasInterceptors := false for i, svc := range svr.Services { sd := service.Services.Get(svc) svcData[i] = sd specs = append(specs, &codegen.ImportSpec{ Path: path.Join(genpkg, sd.PathName), - Name: scope.Unique(sd.PkgName), + Name: scope.Unique(sd.PkgName, "svc"), }) + hasInterceptors = hasInterceptors || len(sd.ServerInterceptors) > 0 } + interPkg := scope.Unique("interceptors", "ex") var ( rootPath string @@ -73,6 +76,9 @@ func exampleSvrMain(genpkg string, root *expr.RootExpr, svr *expr.ServerExpr) *c apiPkg = scope.Unique(strings.ToLower(codegen.Goify(root.API.Name, false)), "api") } specs = append(specs, &codegen.ImportSpec{Path: rootPath, Name: apiPkg}) + if hasInterceptors { + specs = append(specs, &codegen.ImportSpec{Path: path.Join(rootPath, "interceptors"), Name: interPkg}) + } sections := []*codegen.SectionTemplate{ codegen.Header("", "main", specs), @@ -101,6 +107,18 @@ func exampleSvrMain(genpkg string, root *expr.RootExpr, svr *expr.ServerExpr) *c FuncMap: map[string]any{ "mustInitServices": mustInitServices, }, + }, { + Name: "server-main-interceptors", + Source: readTemplate("server_interceptors"), + Data: map[string]any{ + "APIPkg": apiPkg, + "InterPkg": interPkg, + "Services": svcData, + "HasInterceptors": hasInterceptors, + }, + FuncMap: map[string]any{ + "mustInitServices": mustInitServices, + }, }, { Name: "server-main-endpoints", Source: readTemplate("server_endpoints"), diff --git a/vendor/goa.design/goa/v3/codegen/example/templates/server_endpoints.go.tpl b/vendor/goa.design/goa/v3/codegen/example/templates/server_endpoints.go.tpl index 3916ab3bd4..97be6436ee 100644 --- a/vendor/goa.design/goa/v3/codegen/example/templates/server_endpoints.go.tpl +++ b/vendor/goa.design/goa/v3/codegen/example/templates/server_endpoints.go.tpl @@ -11,7 +11,7 @@ { {{- range .Services }} {{- if .Methods }} - {{ .VarName }}Endpoints = {{ .PkgName }}.NewEndpoints({{ .VarName }}Svc) + {{ .VarName }}Endpoints = {{ .PkgName }}.NewEndpoints({{ .VarName }}Svc{{ if .ServerInterceptors }}, {{ .VarName }}Interceptors{{ end }}) {{ .VarName }}Endpoints.Use(debug.LogPayloads()) {{ .VarName }}Endpoints.Use(log.Endpoint) {{- end }} diff --git a/vendor/goa.design/goa/v3/codegen/example/templates/server_interceptors.go.tpl b/vendor/goa.design/goa/v3/codegen/example/templates/server_interceptors.go.tpl new file mode 100644 index 0000000000..c2b09fcae3 --- /dev/null +++ b/vendor/goa.design/goa/v3/codegen/example/templates/server_interceptors.go.tpl @@ -0,0 +1,19 @@ +{{- if mustInitServices .Services }} + {{- if .HasInterceptors }} + {{ comment "Initialize the interceptors." }} + var ( + {{- range .Services }} + {{- if and .Methods .ServerInterceptors }} + {{ .VarName }}Interceptors {{ .PkgName }}.ServerInterceptors + {{- end }} + {{- end }} + ) + { + {{- range .Services }} + {{- if and .Methods .ServerInterceptors }} + {{ .VarName }}Interceptors = {{ $.InterPkg }}.New{{ .StructName }}ServerInterceptors() + {{- end }} + {{- end }} + } + {{- end }} +{{- end }} \ No newline at end of file diff --git a/vendor/goa.design/goa/v3/codegen/generator/example.go b/vendor/goa.design/goa/v3/codegen/generator/example.go index c78545a3f7..827880149f 100644 --- a/vendor/goa.design/goa/v3/codegen/generator/example.go +++ b/vendor/goa.design/goa/v3/codegen/generator/example.go @@ -25,6 +25,11 @@ func Example(genpkg string, roots []eval.Root) ([]*codegen.File, error) { files = append(files, fs...) } + // example interceptors implementation + if fs := service.ExampleInterceptorsFiles(genpkg, r); len(fs) != 0 { + files = append(files, fs...) + } + // server main if fs := example.ServerFiles(genpkg, r); len(fs) != 0 { files = append(files, fs...) @@ -54,6 +59,8 @@ func Example(genpkg string, roots []eval.Root) ([]*codegen.File, error) { files = append(files, fs...) } } + + // Add imports defined via struct:field:type for _, f := range files { if len(f.SectionTemplates) > 0 { for _, s := range r.Services { diff --git a/vendor/goa.design/goa/v3/codegen/goify.go b/vendor/goa.design/goa/v3/codegen/goify.go index b6caae5549..3c26c8d335 100644 --- a/vendor/goa.design/goa/v3/codegen/goify.go +++ b/vendor/goa.design/goa/v3/codegen/goify.go @@ -1,6 +1,8 @@ package codegen import ( + "go/doc" + "go/token" "strings" "goa.design/goa/v3/expr" @@ -54,70 +56,14 @@ func UnionValTypeName(unionName string) string { // fixReservedGo appends an underscore on to Go reserved keywords. func fixReservedGo(w string) string { - if reservedGo[w] { + if doc.IsPredeclared(w) || token.IsKeyword(w) || isPackage[w] { w += "_" } return w } var ( - // reserved golang keywords and package names - reservedGo = map[string]bool{ - // predeclared types - "bool": true, - "byte": true, - "complex128": true, - "complex64": true, - "float32": true, - "float64": true, - "int": true, - "int16": true, - "int32": true, - "int64": true, - "int8": true, - "rune": true, - "string": true, - "uint": true, - "uint16": true, - "uint32": true, - "uint64": true, - "uint8": true, - "uintptr": true, - - // reserved keywords - "break": true, - "case": true, - "chan": true, - "const": true, - "continue": true, - "default": true, - "defer": true, - "delete": true, - "else": true, - "fallthrough": true, - "for": true, - "func": true, - "go": true, - "goto": true, - "if": true, - "import": true, - "interface": true, - "map": true, - "package": true, - "range": true, - "return": true, - "select": true, - "struct": true, - "switch": true, - "type": true, - "var": true, - - // predeclared constants - "true": true, - "false": true, - "iota": true, - "nil": true, - + isPackage = map[string]bool{ // stdlib and goa packages used by generated code "fmt": true, "http": true, diff --git a/vendor/goa.design/goa/v3/codegen/service/client.go b/vendor/goa.design/goa/v3/codegen/service/client.go index a088de0d37..8cc61b2dc4 100644 --- a/vendor/goa.design/goa/v3/codegen/service/client.go +++ b/vendor/goa.design/goa/v3/codegen/service/client.go @@ -15,7 +15,7 @@ const ( // ClientFile returns the client file for the given service. func ClientFile(_ string, service *expr.ServiceExpr) *codegen.File { svc := Services.Get(service.Name) - data := endpointData(service) + data := endpointData(svc) path := filepath.Join(codegen.Gendir, svc.PathName, "client.go") var ( sections []*codegen.SectionTemplate diff --git a/vendor/goa.design/goa/v3/codegen/service/convert.go b/vendor/goa.design/goa/v3/codegen/service/convert.go index a54b2b68b8..7d6c801a7f 100644 --- a/vendor/goa.design/goa/v3/codegen/service/convert.go +++ b/vendor/goa.design/goa/v3/codegen/service/convert.go @@ -213,8 +213,7 @@ func ConvertFile(root *expr.RootExpr, service *expr.ServiceExpr) (*codegen.File, } // Build header section - pkgs = append(pkgs, &codegen.ImportSpec{Path: "context"}) - pkgs = append(pkgs, codegen.GoaImport("")) + pkgs = append(pkgs, &codegen.ImportSpec{Path: "context"}, codegen.GoaImport("")) path := filepath.Join(codegen.Gendir, codegen.SnakeCase(service.Name), "convert.go") sections := []*codegen.SectionTemplate{ codegen.Header(service.Name+" service type conversion functions", svc.PkgName, pkgs), @@ -238,8 +237,10 @@ func ConvertFile(root *expr.RootExpr, service *expr.ServiceExpr) (*codegen.File, srcCtx := typeContext("", svc.Scope) tgtCtx := codegen.NewAttributeContext(false, false, false, tgtPkg, codegen.NewNameScope()) srcAtt := &expr.AttributeExpr{Type: c.User} + tgtAtt := &expr.AttributeExpr{Type: dt} + tgtAtt.AddMeta("struct:type:name", dt.Name()) // Used by transformer to generate the correct type name. code, tf, err := codegen.GoTransform( - &expr.AttributeExpr{Type: c.User}, &expr.AttributeExpr{Type: dt}, + srcAtt, tgtAtt, "t", "v", srcCtx, tgtCtx, "transform", true) if err != nil { return nil, err @@ -696,24 +697,22 @@ func compatible(from expr.DataType, to reflect.Type, recs ...compRec) error { ok bool field reflect.StructField ) - { - if ef, k := nat.Attribute.Meta["struct:field:external"]; k { - fname = ef[0] - if fname == "-" { - continue - } - field, ok = to.FieldByName(ef[0]) - } else if ef, k := nat.Attribute.Meta["struct.field.external"]; k { // Deprecated syntax. Only present for backward compatibility. - fname = ef[0] - if fname == "-" { - continue - } - field, ok = to.FieldByName(ef[0]) - } else { - ef := codegen.Goify(ma.ElemName(nat.Name), true) - fname = ef - field, ok = to.FieldByName(ef) + if ef, k := nat.Attribute.Meta["struct:field:external"]; k { + fname = ef[0] + if fname == "-" { + continue } + field, ok = to.FieldByName(ef[0]) + } else if ef, k := nat.Attribute.Meta["struct.field.external"]; k { // Deprecated syntax. Only present for backward compatibility. + fname = ef[0] + if fname == "-" { + continue + } + field, ok = to.FieldByName(ef[0]) + } else { + ef := codegen.Goify(ma.ElemName(nat.Name), true) + fname = ef + field, ok = to.FieldByName(ef) } if !ok { return fmt.Errorf("types don't match: could not find field %q of external type %q matching attribute %q of type %q", diff --git a/vendor/goa.design/goa/v3/codegen/service/endpoint.go b/vendor/goa.design/goa/v3/codegen/service/endpoint.go index aaefc4bbd2..8ca7156704 100644 --- a/vendor/goa.design/goa/v3/codegen/service/endpoint.go +++ b/vendor/goa.design/goa/v3/codegen/service/endpoint.go @@ -30,6 +30,12 @@ type ( // Schemes contains the security schemes types used by the // all the endpoints. Schemes SchemesData + // HasServerInterceptors indicates that the service has server-side + // interceptors. + HasServerInterceptors bool + // HasClientInterceptors indicates that the service has client-side + // interceptors. + HasClientInterceptors bool } // EndpointMethodData describes a single endpoint method. @@ -61,7 +67,7 @@ func EndpointFile(genpkg string, service *expr.ServiceExpr) *codegen.File { svc := Services.Get(service.Name) svcName := svc.PathName path := filepath.Join(codegen.Gendir, svcName, "endpoints.go") - data := endpointData(service) + data := endpointData(svc) var ( sections []*codegen.SectionTemplate ) @@ -128,8 +134,7 @@ func EndpointFile(genpkg string, service *expr.ServiceExpr) *codegen.File { return &codegen.File{Path: path, SectionTemplates: sections} } -func endpointData(service *expr.ServiceExpr) *EndpointsData { - svc := Services.Get(service.Name) +func endpointData(svc *Data) *EndpointsData { methods := make([]*EndpointMethodData, len(svc.Methods)) names := make([]string, len(svc.Methods)) for i, m := range svc.Methods { @@ -142,16 +147,18 @@ func endpointData(service *expr.ServiceExpr) *EndpointsData { } names[i] = codegen.Goify(m.VarName, false) } - desc := fmt.Sprintf("%s wraps the %q service endpoints.", endpointsStructName, service.Name) + desc := fmt.Sprintf("%s wraps the %q service endpoints.", endpointsStructName, svc.Name) return &EndpointsData{ - Name: service.Name, - Description: desc, - VarName: endpointsStructName, - ClientVarName: clientStructName, - ServiceVarName: serviceInterfaceName, - ClientInitArgs: strings.Join(names, ", "), - Methods: methods, - Schemes: svc.Schemes, + Name: svc.Name, + Description: desc, + VarName: endpointsStructName, + ClientVarName: clientStructName, + ServiceVarName: serviceInterfaceName, + ClientInitArgs: strings.Join(names, ", "), + Methods: methods, + Schemes: svc.Schemes, + HasServerInterceptors: len(svc.ServerInterceptors) > 0, + HasClientInterceptors: len(svc.ClientInterceptors) > 0, } } diff --git a/vendor/goa.design/goa/v3/codegen/service/example_interceptors.go b/vendor/goa.design/goa/v3/codegen/service/example_interceptors.go new file mode 100644 index 0000000000..7c24b08bea --- /dev/null +++ b/vendor/goa.design/goa/v3/codegen/service/example_interceptors.go @@ -0,0 +1,86 @@ +package service + +import ( + "fmt" + "os" + "path" + "path/filepath" + + "goa.design/goa/v3/codegen" + "goa.design/goa/v3/expr" +) + +// ExampleInterceptorsFiles returns the files for the example server and client interceptors. +func ExampleInterceptorsFiles(genpkg string, r *expr.RootExpr) []*codegen.File { + var fw []*codegen.File + for _, svc := range r.Services { + if f := exampleInterceptorsFile(genpkg, svc); f != nil { + fw = append(fw, f...) + } + } + return fw +} + +// exampleInterceptorsFile returns the example interceptors for the given service. +func exampleInterceptorsFile(genpkg string, svc *expr.ServiceExpr) []*codegen.File { + sdata := Services.Get(svc.Name) + data := map[string]any{ + "ServiceName": sdata.Name, + "StructName": sdata.StructName, + "PkgName": "interceptors", + "ServerInterceptors": sdata.ServerInterceptors, + "ClientInterceptors": sdata.ClientInterceptors, + } + + var files []*codegen.File + + // Generate server interceptor if needed and file doesn't exist + if len(sdata.ServerInterceptors) > 0 { + serverPath := filepath.Join("interceptors", sdata.PathName+"_server.go") + if _, err := os.Stat(serverPath); os.IsNotExist(err) { + files = append(files, &codegen.File{ + Path: serverPath, + SectionTemplates: []*codegen.SectionTemplate{ + codegen.Header(fmt.Sprintf("%s example server interceptors", sdata.Name), "interceptors", []*codegen.ImportSpec{ + {Path: "context"}, + {Path: "fmt"}, + {Path: "goa.design/clue/log"}, + codegen.GoaImport(""), + {Path: path.Join(genpkg, sdata.PathName), Name: sdata.PkgName}, + }), + { + Name: "exmaple-server-interceptor", + Source: readTemplate("example_server_interceptor"), + Data: data, + }, + }, + }) + } + } + + // Generate client interceptor if needed and file doesn't exist + if len(sdata.ClientInterceptors) > 0 { + clientPath := filepath.Join("interceptors", sdata.PathName+"_client.go") + if _, err := os.Stat(clientPath); os.IsNotExist(err) { + files = append(files, &codegen.File{ + Path: clientPath, + SectionTemplates: []*codegen.SectionTemplate{ + codegen.Header(fmt.Sprintf("%s example client interceptors", sdata.Name), "interceptors", []*codegen.ImportSpec{ + {Path: "context"}, + {Path: "fmt"}, + {Path: "goa.design/clue/log"}, + codegen.GoaImport(""), + {Path: path.Join(genpkg, sdata.PathName), Name: sdata.PkgName}, + }), + { + Name: "example-client-interceptor", + Source: readTemplate("example_client_interceptor"), + Data: data, + }, + }, + }) + } + } + + return files +} diff --git a/vendor/goa.design/goa/v3/codegen/service/example_svc.go b/vendor/goa.design/goa/v3/codegen/service/example_svc.go index 7f4b156054..46b977eff1 100644 --- a/vendor/goa.design/goa/v3/codegen/service/example_svc.go +++ b/vendor/goa.design/goa/v3/codegen/service/example_svc.go @@ -78,18 +78,18 @@ func exampleServiceFile(genpkg string, _ *expr.RootExpr, svc *expr.ServiceExpr, codegen.Header("", apipkg, specs), { Name: "basic-service-struct", - Source: readTemplate("service_struct"), + Source: readTemplate("example_service_struct"), Data: data, }, { Name: "basic-service-init", - Source: readTemplate("service_init"), + Source: readTemplate("example_service_init"), Data: data, }, } if len(data.Schemes) > 0 { sections = append(sections, &codegen.SectionTemplate{ Name: "security-authfuncs", - Source: readTemplate("security_authfuncs"), + Source: readTemplate("example_security_authfuncs"), Data: data, }) } diff --git a/vendor/goa.design/goa/v3/codegen/service/interceptors.go b/vendor/goa.design/goa/v3/codegen/service/interceptors.go new file mode 100644 index 0000000000..ef70bd2924 --- /dev/null +++ b/vendor/goa.design/goa/v3/codegen/service/interceptors.go @@ -0,0 +1,265 @@ +package service + +import ( + "path/filepath" + + "goa.design/goa/v3/codegen" + "goa.design/goa/v3/expr" +) + +// InterceptorsFiles returns the interceptors files for the given service. +func InterceptorsFiles(_ string, service *expr.ServiceExpr) []*codegen.File { + var files []*codegen.File + svc := Services.Get(service.Name) + + // Generate service-specific interceptor files + if len(svc.ServerInterceptors) > 0 { + files = append(files, interceptorFile(svc, true)) + } + if len(svc.ClientInterceptors) > 0 { + files = append(files, interceptorFile(svc, false)) + } + + // Generate wrapper file if this service has any interceptors + if len(svc.ServerInterceptors) > 0 || len(svc.ClientInterceptors) > 0 { + files = append(files, wrapperFile(svc)) + } + + return files +} + +// interceptorFile returns the file defining the interceptors. +// This method is called twice, once for the server and once for the client. +func interceptorFile(svc *Data, server bool) *codegen.File { + filename := "client_interceptors.go" + template := "client_interceptors" + section := "client-interceptors-type" + desc := "Client Interceptors" + if server { + filename = "service_interceptors.go" + template = "server_interceptors" + section = "server-interceptors-type" + desc = "Server Interceptors" + } + desc = svc.Name + desc + path := filepath.Join(codegen.Gendir, svc.PathName, filename) + + interceptors := svc.ServerInterceptors + if !server { + interceptors = svc.ClientInterceptors + } + + // We don't want to generate duplicate interceptor info data structures for + // interceptors that are both server and client side so remove interceptors + // that are both server and client side when generating the client. + if !server { + names := make(map[string]struct{}, len(svc.ServerInterceptors)) + for _, sin := range svc.ServerInterceptors { + names[sin.Name] = struct{}{} + } + filtered := make([]*InterceptorData, 0, len(interceptors)) + for _, in := range interceptors { + if _, ok := names[in.Name]; !ok { + filtered = append(filtered, in) + } + } + interceptors = filtered + } + + sections := []*codegen.SectionTemplate{ + codegen.Header(desc, svc.PkgName, []*codegen.ImportSpec{ + {Path: "context"}, + codegen.GoaImport(""), + }), + { + Name: section, + Source: readTemplate(template), + Data: svc, + }, + } + if len(interceptors) > 0 { + codegen.AddImport(sections[0], svc.UserTypeImports...) + sections = append(sections, &codegen.SectionTemplate{ + Name: "interceptor-types", + Source: readTemplate("interceptors_types"), + Data: interceptors, + FuncMap: map[string]any{ + "hasPrivateImplementationTypes": hasPrivateImplementationTypes, + }, + }) + } + + template = "endpoint_wrappers" + section = "endpoint-wrapper" + if !server { + template = "client_wrappers" + section = "client-wrapper" + } + for _, m := range svc.Methods { + ints := m.ServerInterceptors + if !server { + ints = m.ClientInterceptors + } + if len(ints) == 0 { + continue + } + sections = append(sections, &codegen.SectionTemplate{ + Name: section, + Source: readTemplate(template), + Data: map[string]interface{}{ + "MethodVarName": m.VarName, + "Method": m.Name, + "Service": svc.Name, + "Interceptors": ints, + }, + }) + } + + if len(interceptors) > 0 { + sections = append(sections, &codegen.SectionTemplate{ + Name: "interceptors", + Source: readTemplate("interceptors"), + Data: interceptors, + FuncMap: map[string]any{ + "hasPrivateImplementationTypes": hasPrivateImplementationTypes, + "hasEndpointStruct": hasEndpointStruct(server), + }, + }) + } + + return &codegen.File{Path: path, SectionTemplates: sections} +} + +// wrapperFile returns the file containing the interceptor wrappers. +func wrapperFile(svc *Data) *codegen.File { + path := filepath.Join(codegen.Gendir, svc.PathName, "interceptor_wrappers.go") + + var sections []*codegen.SectionTemplate + sections = append(sections, codegen.Header("Interceptor wrappers", svc.PkgName, []*codegen.ImportSpec{ + {Path: "context"}, + {Path: "fmt"}, + codegen.GoaImport(""), + })) + + // Generate any interceptor stream wrapper struct types first + var wrappedServerStreams, wrappedClientStreams []*StreamInterceptorData + if len(svc.ServerInterceptors) > 0 { + wrappedServerStreams = collectWrappedStreams(svc.ServerInterceptors, true) + if len(wrappedServerStreams) > 0 { + sections = append(sections, &codegen.SectionTemplate{ + Name: "server-interceptor-stream-wrapper-types", + Source: readTemplate("server_interceptor_stream_wrapper_types"), + Data: map[string]interface{}{ + "WrappedServerStreams": wrappedServerStreams, + }, + }) + } + } + if len(svc.ClientInterceptors) > 0 { + wrappedClientStreams = collectWrappedStreams(svc.ClientInterceptors, false) + if len(wrappedClientStreams) > 0 { + sections = append(sections, &codegen.SectionTemplate{ + Name: "client-interceptor-stream-wrapper-types", + Source: readTemplate("client_interceptor_stream_wrapper_types"), + Data: map[string]interface{}{ + "WrappedClientStreams": wrappedClientStreams, + }, + }) + } + } + + // Generate the interceptor wrapper functions next (only once) + if len(svc.ServerInterceptors) > 0 { + sections = append(sections, &codegen.SectionTemplate{ + Name: "server-interceptor-wrappers", + Source: readTemplate("server_interceptor_wrappers"), + Data: map[string]interface{}{ + "Service": svc.Name, + "ServerInterceptors": svc.ServerInterceptors, + }, + }) + } + if len(svc.ClientInterceptors) > 0 { + sections = append(sections, &codegen.SectionTemplate{ + Name: "client-interceptor-wrappers", + Source: readTemplate("client_interceptor_wrappers"), + Data: map[string]interface{}{ + "Service": svc.Name, + "ClientInterceptors": svc.ClientInterceptors, + }, + }) + } + + // Generate any interceptor stream wrapper struct methods last + if len(wrappedServerStreams) > 0 { + sections = append(sections, &codegen.SectionTemplate{ + Name: "server-interceptor-stream-wrappers", + Source: readTemplate("server_interceptor_stream_wrappers"), + Data: map[string]interface{}{ + "WrappedServerStreams": wrappedServerStreams, + }, + }) + } + if len(wrappedClientStreams) > 0 { + sections = append(sections, &codegen.SectionTemplate{ + Name: "client-interceptor-stream-wrappers", + Source: readTemplate("client_interceptor_stream_wrappers"), + Data: map[string]interface{}{ + "WrappedClientStreams": wrappedClientStreams, + }, + }) + } + + return &codegen.File{ + Path: path, + SectionTemplates: sections, + } +} + +// hasPrivateImplementationTypes returns true if any of the interceptors have +// private implementation types. +func hasPrivateImplementationTypes(interceptors []*InterceptorData) bool { + for _, intr := range interceptors { + if intr.ReadPayload != nil || intr.WritePayload != nil || intr.ReadResult != nil || intr.WriteResult != nil || intr.ReadStreamingPayload != nil || intr.WriteStreamingPayload != nil || intr.ReadStreamingResult != nil || intr.WriteStreamingResult != nil { + return true + } + } + return false +} + +// hasEndpointStruct returns a function that returns true if the method has an endpoint struct +// if server is true, otherwise it returns false. +func hasEndpointStruct(server bool) func(*MethodInterceptorData) bool { + if !server { + return func(*MethodInterceptorData) bool { return false } + } + return func(m *MethodInterceptorData) bool { + return m.ServerStream != nil && m.ServerStream.EndpointStruct != "" + } +} + +// collectWrappedStreams returns a slice of streams to be wrapped by interceptor wrapper functions. +func collectWrappedStreams(interceptors []*InterceptorData, server bool) []*StreamInterceptorData { + var ( + streams []*StreamInterceptorData + streamNames = make(map[string]struct{}) + ) + for _, intr := range interceptors { + if intr.HasStreamingPayloadAccess || intr.HasStreamingResultAccess { + for _, method := range intr.Methods { + if server { + if _, ok := streamNames[method.ServerStream.Interface]; !ok { + streams = append(streams, method.ServerStream) + streamNames[method.ServerStream.Interface] = struct{}{} + } + } else { + if _, ok := streamNames[method.ClientStream.Interface]; !ok { + streams = append(streams, method.ClientStream) + streamNames[method.ClientStream.Interface] = struct{}{} + } + } + } + } + } + return streams +} diff --git a/vendor/goa.design/goa/v3/codegen/service/interceptors.md b/vendor/goa.design/goa/v3/codegen/service/interceptors.md new file mode 100644 index 0000000000..f5fd436c30 --- /dev/null +++ b/vendor/goa.design/goa/v3/codegen/service/interceptors.md @@ -0,0 +1,163 @@ +# Interceptors Code Generation + +Goa generates interceptor code to enable request/response interception and payload/result access. + +--- + +## 1. Client & Server Interceptors + +### Where They Are Generated + +Client and server interceptor code is generated in: + +* `gen/client_interceptors.go` +* `gen/service_interceptors.go` + +### Templates Used + +1. **`server_interceptors.go.tpl`** and **`client_interceptors.go.tpl`** + Define the server and client interceptor interface types. + Each template takes a `Data` struct as input. + +2. **`interceptors.go.tpl`** + Generates the payload/result access interfaces and accompanying info structs. + This template takes a slice of `InterceptorData` as input. + +3. **`client_wrappers.go.tpl`** and **`endpoint_wrappers.go.tpl`** + Generate code that wraps client and service endpoints with interceptor callbacks. + Each template takes a map with: + + ```go + map[string]any{ + "MethodVarName": + "Method": + "Service": + "Interceptors": + } + ``` + +--- + +## 2. Client & Server Endpoint Wrapper Code + +### Where It Is Generated + +Endpoint wrapper code for both client and server interceptors is generated in: + +* `gen/interceptor_wrappers.go` + +### Templates Used + +1. **`server_interceptor_wrappers.go.tpl`** + Generates server-specific wrapper implementations. This template receives a map with: + + ```go + map[string]any{ + "Service": svc.Name, + "ServerInterceptors": svc.ServerInterceptors, + } + ``` + +2. **`client_interceptor_wrappers.go.tpl`** + Generates client-specific wrapper implementations. This template receives a map with: + + ```go + map[string]any{ + "Service": svc.Name, + "ClientInterceptors": svc.ClientInterceptors, + } + ``` + +## 3. Example Interceptors + +### Where They Are Generated + +Example interceptors are generated by the example command in an interceptors sub-package of the user’s service package: + +* Client interceptors: `_client.go` +* Server interceptors: `_server.go` + +### Templates Used + +1. **`example_client_interceptor.go.tpl` and `example_server_interceptor.go.tpl`** + Generate example interceptor implementations. Each template takes a map with: + + ```go + map[string]any{ + "StructName": + "ServiceName": + "PkgName": + "ServerInterceptors": + "ClientInterceptors": + } + ``` + +2. **`example_service_init.go.tpl`** + Generates an example service implementation. This template takes a Data struct. + +### Generated Example Features + +The example interceptors demonstrate common interception patterns: + +* Logging of request/response data +* Error handling and error logging +* Type-safe payload and result access through the generated info structs +* Context propagation across requests and responses + +## 4. Data Structures + +The templates above share a common set of data structures that describe +interceptor behavior, payload, result access, and streaming. These data +structures are defined as follows: + +### `Data` + +A service-level structure containing information for both client and server interceptors: + +* `ServerInterceptors`: A slice of InterceptorData for server-side interceptors +* `ClientInterceptors`: A slice of InterceptorData for client-side interceptors + +### `InterceptorData` + +The main structure describing each interceptor’s metadata and requirements: + +* `Name`: Generated Go name of the interceptor (CamelCase) +* `DesignName`: Original name from the design +* `Description`: Interceptor description from the design +* `HasPayloadAccess`: Indicates if any method requires payload access +* `HasResultAccess`: Indicates if any method requires result access +* `HasStreamingPayloadAccess`: Indicates if any method requires streaming payload access +* `HasStreamingResultAccess`: Indicates if any method requires streaming result access +* `ReadPayload`: List of readable payload fields ([]AttributeData) +* `WritePayload`: List of writable payload fields ([]AttributeData) +* `ReadResult`: List of readable result fields ([]AttributeData) +* `WriteResult`: List of writable result fields ([]AttributeData) +* `ReadStreamingPayload`: List of readable streaming payload fields ([]AttributeData) +* `WriteStreamingPayload`: List of writable streaming payload fields ([]AttributeData) +* `ReadStreamingResult`: List of readable streaming result fields ([]AttributeData) +* `WriteStreamingResult`: List of writable streaming result fields ([]AttributeData) +* `Methods`: A list of MethodInterceptorData containing method-specific interceptor information +* `ServerStreamInputStruct`: Server stream variable name (used if streaming) +* `ClientStreamInputStruct`: Client stream variable name (used if streaming) + +### `MethodInterceptorData` + +Stores per-method interceptor configuration: + +* `MethodName`: The method’s Go variable name +* `PayloadAccess`: Name of the payload access type +* `ResultAccess`: Name of the result access type +* `StreamingPayloadAccess`: Name of the streaming payload access type +* `StreamingResultAccess`: Name of the streaming result access type +* `PayloadRef`: Reference to the method's payload type +* `ResultRef`: Reference to the method's result type +* `StreamingPayloadRef`: Reference to the method's streaming payload type +* `StreamingResultRef`: Reference to the method's streaming result type + +### `AttributeData` + +Represents per-field access configuration: + +* `Name`: The field accessor method name +* `TypeRef`: Go type reference for the field +* `Type`: Underlying attribute type information diff --git a/vendor/goa.design/goa/v3/codegen/service/service.go b/vendor/goa.design/goa/v3/codegen/service/service.go index 8d920c7854..bc900ce79f 100644 --- a/vendor/goa.design/goa/v3/codegen/service/service.go +++ b/vendor/goa.design/goa/v3/codegen/service/service.go @@ -47,7 +47,7 @@ func Files(genpkg string, service *expr.ServiceExpr, userTypePkgs map[string][]s if m.StreamingPayloadDef != "" { if _, ok := seen[m.StreamingPayload]; !ok { addTypeDefSection(payloadPath, m.StreamingPayload, &codegen.SectionTemplate{ - Name: "service-streamig-payload", + Name: "service-streaming-payload", Source: readTemplate("streaming_payload"), Data: m, }) @@ -122,16 +122,9 @@ func Files(genpkg string, service *expr.ServiceExpr, userTypePkgs map[string][]s // transform result type functions for _, t := range svc.viewedResultTypes { - svcSections = append(svcSections, &codegen.SectionTemplate{ - Name: "viewed-result-type-to-service-result-type", - Source: readTemplate("type_init"), - Data: t.ResultInit, - }) - svcSections = append(svcSections, &codegen.SectionTemplate{ - Name: "service-result-type-to-viewed-result-type", - Source: readTemplate("type_init"), - Data: t.Init, - }) + svcSections = append(svcSections, + &codegen.SectionTemplate{Name: "viewed-result-type-to-service-result-type", Source: readTemplate("type_init"), Data: t.ResultInit}, + &codegen.SectionTemplate{Name: "service-result-type-to-viewed-result-type", Source: readTemplate("type_init"), Data: t.Init}) } var projh []*codegen.TransformFunctionData for _, t := range svc.projectedTypes { @@ -195,6 +188,9 @@ func Files(genpkg string, service *expr.ServiceExpr, userTypePkgs map[string][]s } files := []*codegen.File{{Path: svcPath, SectionTemplates: sections}} + // service and client interceptors + files = append(files, InterceptorsFiles(genpkg, service)...) + // user types paths := make([]string, len(typeDefSections)) i := 0 diff --git a/vendor/goa.design/goa/v3/codegen/service/service_data.go b/vendor/goa.design/goa/v3/codegen/service/service_data.go index f0a62f81cb..e62dd4ea71 100644 --- a/vendor/goa.design/goa/v3/codegen/service/service_data.go +++ b/vendor/goa.design/goa/v3/codegen/service/service_data.go @@ -37,12 +37,6 @@ type ( // ServicesData encapsulates the data computed from the service designs. ServicesData map[string]*Data - // RequirementsData is the list of security requirements. - RequirementsData []*RequirementData - - // SchemesData is the list of security schemes. - SchemesData []*SchemeData - // Data contains the data used to render the code related to a single // service. Data struct { @@ -70,6 +64,12 @@ type ( Methods []*MethodData // Schemes is the list of security schemes required by the service methods. Schemes SchemesData + // ServerInterceptors contains the data needed to render the server-side + // interceptors code. + ServerInterceptors []*InterceptorData + // ClientInterceptors contains the data needed to render the client-side + // interceptors code. + ClientInterceptors []*InterceptorData // Scope initialized with all the service types. Scope *codegen.NameScope // ViewScope initialized with all the viewed types. @@ -99,38 +99,6 @@ type ( unionValueMethods []*UnionValueMethodData } - // UnionValueMethodData describes a method used on a union value type. - UnionValueMethodData struct { - // Name is the name of the function. - Name string - // TypeRef is a reference on the target union value type. - TypeRef string - // Loc defines the file and Go package of the method if - // overridden in corresponding union type via Meta. - Loc *codegen.Location - } - - // ErrorInitData describes an error returned by a service method of type - // ErrorResult. - ErrorInitData struct { - // Name is the name of the init function. - Name string - // Description is the error description. - Description string - // ErrName is the name of the error. - ErrName string - // TypeName is the error struct type name. - TypeName string - // TypeRef is the reference to the error type. - TypeRef string - // Temporary indicates whether the error is temporary. - Temporary bool - // Timeout indicates whether the error is due to timeouts. - Timeout bool - // Fault indicates whether the error is server-side fault. - Fault bool - } - // MethodData describes a single service method. MethodData struct { // Name is the method name. @@ -188,6 +156,12 @@ type ( // Schemes contains the security schemes types used by the // method. Schemes SchemesData + // ServerInterceptors list the server interceptors that apply to this + // method. + ServerInterceptors []string + // ClientInterceptors list the client interceptors that apply to this + // method. + ClientInterceptors []string // ViewedResult contains the data required to generate the code handling // views if any. ViewedResult *ViewedResultTypeData @@ -229,6 +203,10 @@ type ( SendName string // SendDesc is the description for the send function. SendDesc string + // SendWithContextName is the name of the send function with context. + SendWithContextName string + // SendWithContextDesc is the description for the send function with context. + SendWithContextDesc string // SendTypeName is the type name sent through the stream. SendTypeName string // SendTypeRef is the reference to the type sent through the stream. @@ -237,6 +215,10 @@ type ( RecvName string // RecvDesc is the description for the recv function. RecvDesc string + // RecvWithContextName is the name of the receive function with context. + RecvWithContextName string + // RecvWithContextDesc is the description for the recv function with context. + RecvWithContextDesc string // RecvTypeName is the type name received from the stream. RecvTypeName string // RecvTypeRef is the reference to the type received from the stream. @@ -245,13 +227,144 @@ type ( // function. MustClose bool // EndpointStruct is the name of the endpoint struct that holds a payload - // reference (if any) and the endpoint server stream. It is set only if the - // client sends a normal payload and server streams a result. + // reference (if any) and the endpoint server stream. EndpointStruct string // Kind is the kind of the stream (payload, result or bidirectional). Kind expr.StreamKind } + // ErrorInitData describes an error returned by a service method of type + // ErrorResult. + ErrorInitData struct { + // Name is the name of the init function. + Name string + // Description is the error description. + Description string + // ErrName is the name of the error. + ErrName string + // TypeName is the error struct type name. + TypeName string + // TypeRef is the reference to the error type. + TypeRef string + // Temporary indicates whether the error is temporary. + Temporary bool + // Timeout indicates whether the error is due to timeouts. + Timeout bool + // Fault indicates whether the error is server-side fault. + Fault bool + } + + // InterceptorData contains the data required to render the service-level + // interceptor code. interceptors.go.tpl + InterceptorData struct { + // Name is the name of the interceptor used in the generated code. + Name string + // DesignName is the name of the interceptor as defined in the design. + DesignName string + // Description is the description of the interceptor from the design. + Description string + // Methods + Methods []*MethodInterceptorData + // ReadPayload contains payload attributes that the interceptor can + // read. + ReadPayload []*AttributeData + // WritePayload contains payload attributes that the interceptor can + // write. + WritePayload []*AttributeData + // ReadResult contains result attributes that the interceptor can read. + ReadResult []*AttributeData + // WriteResult contains result attributes that the interceptor can + // write. + WriteResult []*AttributeData + // ReadStreamingPayload contains streaming payload attributes that the interceptor can read. + ReadStreamingPayload []*AttributeData + // WriteStreamingPayload contains streaming payload attributes that the interceptor can write. + WriteStreamingPayload []*AttributeData + // ReadStreamingResult contains streaming result attributes that the interceptor can read. + ReadStreamingResult []*AttributeData + // WriteStreamingResult contains streaming result attributes that the interceptor can write. + WriteStreamingResult []*AttributeData + // HasPayloadAccess indicates that the interceptor info object has a + // payload access interface. + HasPayloadAccess bool + // HasResultAccess indicates that the interceptor info object has a + // result access interface. + HasResultAccess bool + // HasStreamingPayloadAccess indicates that the interceptor info object has a + // streaming payload access interface. + HasStreamingPayloadAccess bool + // HasStreamingResultAccess indicates that the interceptor info object has a + // streaming result access interface. + HasStreamingResultAccess bool + } + + // MethodInterceptorData contains the data required to render the + // method-level interceptor code. + MethodInterceptorData struct { + // MethodName is the name of the method. + MethodName string + // PayloadAccess is the name of the payload access struct. + PayloadAccess string + // ResultAccess is the name of the result access struct. + ResultAccess string + // StreamingPayloadAccess is the name of the streaming payload access struct. + StreamingPayloadAccess string + // StreamingResultAccess is the name of the streaming result access struct. + StreamingResultAccess string + // PayloadRef is the reference to the method payload type. + PayloadRef string + // ResultRef is the reference to the method result type. + ResultRef string + // StreamingPayloadRef is the reference to the streaming payload type. + StreamingPayloadRef string + // StreamingResultRef is the reference to the streaming result type. + StreamingResultRef string + // ServerStream is the stream data if the endpoint defines a server stream. + ServerStream *StreamInterceptorData + // ClientStream is the stream data if the endpoint defines a client stream. + ClientStream *StreamInterceptorData + } + + // StreamInterceptorData is the stream data for an interceptor. + StreamInterceptorData struct { + // Interface is the name of the stream interface. + Interface string + // SendName is the name of the send function. + SendName string + // SendWithContextName is the name of the send function with context. + SendWithContextName string + // SendTypeRef is the reference to the type sent through the stream. + SendTypeRef string + // RecvName is the name of the recv function. + RecvName string + // RecvWithContextName is the name of the recv function with context. + RecvWithContextName string + // RecvTypeRef is the reference to the type received from the stream. + RecvTypeRef string + // MustClose indicates whether the stream should implement the Close() + // function. + MustClose bool + // EndpointStruct is the name of the endpoint struct that holds a payload + // reference (if any) and the endpoint server stream. + EndpointStruct string + } + + // AttributeData describes a single attribute. + AttributeData struct { + // Name is the name of the attribute. + Name string + // TypeRef is the reference to the attribute type. + TypeRef string + // Pointer is true if the attribute is a pointer. + Pointer bool + } + + // RequirementsData is the list of security requirements. + RequirementsData []*RequirementData + + // SchemesData is the list of security schemes. + SchemesData []*SchemeData + // RequirementData lists the schemes and scopes defined by a single // security requirement. RequirementData struct { @@ -280,6 +393,17 @@ type ( Type expr.UserType } + // UnionValueMethodData describes a method used on a union value type. + UnionValueMethodData struct { + // Name is the name of the function. + Name string + // TypeRef is a reference on the target union value type. + TypeRef string + // Loc defines the file and Go package of the method if + // overridden in corresponding union type via Meta. + Loc *codegen.Location + } + // SchemeData describes a single security scheme. SchemeData struct { // Kind is the type of scheme, one of "Basic", "APIKey", "JWT" @@ -559,94 +683,83 @@ func (s SchemesData) Append(d *SchemeData) SchemesData { // It records the user types needed by the service definition in userTypes. func (d ServicesData) analyze(service *expr.ServiceExpr) *Data { var ( - scope *codegen.NameScope - viewScope *codegen.NameScope - pkgName string - viewspkg string types []*UserTypeData errTypes []*UserTypeData errorInits []*ErrorInitData projTypes []*ProjectedTypeData viewedUnionMeths []*UnionValueMethodData viewedRTs []*ViewedResultTypeData - seenErrors map[string]struct{} - seen map[string]struct{} - seenProj map[string]*ProjectedTypeData - seenViewed map[string]*ViewedResultTypeData ) - { - scope = codegen.NewNameScope() - scope.Unique("Use") // Reserve "Use" for Endpoints struct Use method. - viewScope = codegen.NewNameScope() - pkgName = scope.HashedUnique(service, strings.ToLower(codegen.Goify(service.Name, false)), "svc") - viewspkg = pkgName + "views" - seen = make(map[string]struct{}) - seenErrors = make(map[string]struct{}) - seenProj = make(map[string]*ProjectedTypeData) - seenViewed = make(map[string]*ViewedResultTypeData) - - // A function to collect user types from an error expression - recordError := func(er *expr.ErrorExpr) { - errTypes = append(errTypes, collectTypes(er.AttributeExpr, scope, seen)...) - if er.Type == expr.ErrorResult { - if _, ok := seenErrors[er.Name]; ok { - return - } - seenErrors[er.Name] = struct{}{} - errorInits = append(errorInits, buildErrorInitData(er, scope)) + scope := codegen.NewNameScope() + scope.Unique("Use") // Reserve "Use" for Endpoints struct Use method. + viewScope := codegen.NewNameScope() + pkgName := scope.HashedUnique(service, strings.ToLower(codegen.Goify(service.Name, false)), "svc") + viewspkg := pkgName + "views" + seen := make(map[string]struct{}) + seenErrors := make(map[string]struct{}) + seenProj := make(map[string]*ProjectedTypeData) + seenViewed := make(map[string]*ViewedResultTypeData) + + // A function to collect user types from an error expression + recordError := func(er *expr.ErrorExpr) { + errTypes = append(errTypes, collectTypes(er.AttributeExpr, scope, seen)...) + if er.Type == expr.ErrorResult { + if _, ok := seenErrors[er.Name]; ok { + return } + seenErrors[er.Name] = struct{}{} + errorInits = append(errorInits, buildErrorInitData(er, scope)) } - for _, er := range service.Errors { - recordError(er) - } + } + for _, er := range service.Errors { + recordError(er) + } - // A function to collect inner user types from an attribute expression - collectUserTypes := func(att *expr.AttributeExpr) { - if ut, ok := att.Type.(expr.UserType); ok { - att = ut.Attribute() - } - types = append(types, collectTypes(att, scope, seen)...) - } - for _, m := range service.Methods { - // collect inner user types - collectUserTypes(m.Payload) - collectUserTypes(m.StreamingPayload) - collectUserTypes(m.Result) - // Collect projected types - if hasResultType(m.Result) { - types, umeths := collectProjectedTypes(expr.DupAtt(m.Result), m.Result, viewspkg, scope, viewScope, seenProj) - projTypes = append(projTypes, types...) - viewedUnionMeths = append(viewedUnionMeths, umeths...) - } - for _, er := range m.Errors { - recordError(er) - } + // A function to collect inner user types from an attribute expression + collectUserTypes := func(att *expr.AttributeExpr) { + if ut, ok := att.Type.(expr.UserType); ok { + att = ut.Attribute() + } + types = append(types, collectTypes(att, scope, seen)...) + } + for _, m := range service.Methods { + // collect inner user types + collectUserTypes(m.Payload) + collectUserTypes(m.StreamingPayload) + collectUserTypes(m.Result) + // Collect projected types + if hasResultType(m.Result) { + types, umeths := collectProjectedTypes(expr.DupAtt(m.Result), m.Result, viewspkg, scope, viewScope, seenProj) + projTypes = append(projTypes, types...) + viewedUnionMeths = append(viewedUnionMeths, umeths...) + } + for _, er := range m.Errors { + recordError(er) } + } - // A function to convert raw object type to user type. - wrapObject := func(att *expr.AttributeExpr, name, id string) { - if _, ok := att.Type.(*expr.Object); ok { - att.Type = &expr.UserTypeExpr{ - AttributeExpr: expr.DupAtt(att), - TypeName: scope.Name(name), - UID: id, - } - } - if ut, ok := att.Type.(expr.UserType); ok { - seen[ut.ID()] = struct{}{} + // A function to convert raw object type to user type. + wrapObject := func(att *expr.AttributeExpr, name, id string) { + if _, ok := att.Type.(*expr.Object); ok { + att.Type = &expr.UserTypeExpr{ + AttributeExpr: expr.DupAtt(att), + TypeName: scope.Name(name), + UID: id, } } - - for _, m := range service.Methods { - name := codegen.Goify(m.Name, true) - // Create user type for raw object payloads - wrapObject(m.Payload, name+"Payload", service.Name+"#"+name+"Payload") - // Create user type for raw object streaming payloads - wrapObject(m.StreamingPayload, name+"StreamingPayload", service.Name+"#"+name+"StreamingPayload") - // Create user type for raw object results - wrapObject(m.Result, name+"Result", service.Name+"#"+name+"Result") + if ut, ok := att.Type.(expr.UserType); ok { + seen[ut.ID()] = struct{}{} } + } + for _, m := range service.Methods { + name := codegen.Goify(m.Name, true) + // Create user type for raw object payloads + wrapObject(m.Payload, name+"Payload", service.Name+"#"+name+"Payload") + // Create user type for raw object streaming payloads + wrapObject(m.StreamingPayload, name+"StreamingPayload", service.Name+"#"+name+"StreamingPayload") + // Create user type for raw object results + wrapObject(m.Result, name+"Result", service.Name+"#"+name+"Result") } // Add forced types @@ -674,87 +787,76 @@ func (d ServicesData) analyze(service *expr.ServiceExpr) *Data { methods []*MethodData schemes SchemesData ) - { - methods = make([]*MethodData, len(service.Methods)) - for i, e := range service.Methods { - m := buildMethodData(e, scope) - methods[i] = m - for _, s := range m.Schemes { - schemes = schemes.Append(s) - } - rt, ok := e.Result.Type.(*expr.ResultTypeExpr) - if !ok { - continue - } - var view string - if v, ok := e.Result.Meta.Last(expr.ViewMetaKey); ok { - view = v - } - if vrt, ok := seenViewed[m.Result+"::"+view]; ok { - m.ViewedResult = vrt - continue - } - projected := seenProj[rt.ID()] - projAtt := &expr.AttributeExpr{Type: projected.Type} - vrt := buildViewedResultType(e.Result, projAtt, viewspkg, scope, viewScope) - found := false - for _, rt := range viewedRTs { - if rt.Type.ID() == vrt.Type.ID() { - found = true - break - } - } - if !found { - viewedRTs = append(viewedRTs, vrt) - } + methods = make([]*MethodData, len(service.Methods)) + for i, e := range service.Methods { + m := buildMethodData(e, scope) + methods[i] = m + for _, s := range m.Schemes { + schemes = schemes.Append(s) + } + rt, ok := e.Result.Type.(*expr.ResultTypeExpr) + if !ok { + continue + } + var view string + if v, ok := e.Result.Meta.Last(expr.ViewMetaKey); ok { + view = v + } + if vrt, ok := seenViewed[m.Result+"::"+view]; ok { m.ViewedResult = vrt - seenViewed[vrt.Name+"::"+view] = vrt + continue } - } - - var ( - unionMethods []*UnionValueMethodData - ) - { - var ms []*UnionValueMethodData - seen := make(map[string]struct{}) - for _, t := range types { - ms = append(ms, collectUnionMethods(&expr.AttributeExpr{Type: t.Type}, scope, t.Loc, seen)...) - } - for _, t := range errTypes { - ms = append(ms, collectUnionMethods(&expr.AttributeExpr{Type: t.Type}, scope, t.Loc, seen)...) - } - for _, m := range service.Methods { - ms = append(ms, collectUnionMethods(m.Payload, scope, codegen.UserTypeLocation(m.Payload.Type), seen)...) - ms = append(ms, collectUnionMethods(m.StreamingPayload, scope, codegen.UserTypeLocation(m.StreamingPayload.Type), seen)...) - ms = append(ms, collectUnionMethods(m.Result, scope, codegen.UserTypeLocation(m.Result.Type), seen)...) - for _, e := range m.Errors { - ms = append(ms, collectUnionMethods(e.AttributeExpr, scope, codegen.UserTypeLocation(e.Type), seen)...) + projected := seenProj[rt.ID()] + projAtt := &expr.AttributeExpr{Type: projected.Type} + vrt := buildViewedResultType(e.Result, projAtt, viewspkg, scope, viewScope) + found := false + for _, rt := range viewedRTs { + if rt.Type.ID() == vrt.Type.ID() { + found = true + break } } - sort.Slice(ms, func(i, j int) bool { - return ms[i].Name < ms[j].Name - }) - pkgs := make(map[string]struct{}) - for _, m := range ms { - key := m.TypeRef + "::" + m.Name + "::" + m.Loc.PackageName() - if _, ok := pkgs[key]; ok { - continue - } - pkgs[key] = struct{}{} - unionMethods = append(unionMethods, m) + if !found { + viewedRTs = append(viewedRTs, vrt) } + m.ViewedResult = vrt + seenViewed[vrt.Name+"::"+view] = vrt } - var ( - desc string - ) - { - desc = service.Description - if desc == "" { - desc = fmt.Sprintf("Service is the %s service interface.", service.Name) + var unionMethods []*UnionValueMethodData + var ms []*UnionValueMethodData + seen = make(map[string]struct{}) + for _, t := range types { + ms = append(ms, collectUnionMethods(&expr.AttributeExpr{Type: t.Type}, scope, t.Loc, seen)...) + } + for _, t := range errTypes { + ms = append(ms, collectUnionMethods(&expr.AttributeExpr{Type: t.Type}, scope, t.Loc, seen)...) + } + for _, m := range service.Methods { + ms = append(ms, collectUnionMethods(m.Payload, scope, codegen.UserTypeLocation(m.Payload.Type), seen)...) + ms = append(ms, collectUnionMethods(m.StreamingPayload, scope, codegen.UserTypeLocation(m.StreamingPayload.Type), seen)...) + ms = append(ms, collectUnionMethods(m.Result, scope, codegen.UserTypeLocation(m.Result.Type), seen)...) + for _, e := range m.Errors { + ms = append(ms, collectUnionMethods(e.AttributeExpr, scope, codegen.UserTypeLocation(e.Type), seen)...) } } + sort.Slice(ms, func(i, j int) bool { + return ms[i].Name < ms[j].Name + }) + pkgs := make(map[string]struct{}) + for _, m := range ms { + key := m.TypeRef + "::" + m.Name + "::" + m.Loc.PackageName() + if _, ok := pkgs[key]; ok { + continue + } + pkgs[key] = struct{}{} + unionMethods = append(unionMethods, m) + } + + desc := service.Description + if desc == "" { + desc = fmt.Sprintf("Service is the %s service interface.", service.Name) + } varName := codegen.Goify(service.Name, false) data := &Data{ @@ -769,6 +871,8 @@ func (d ServicesData) analyze(service *expr.ServiceExpr) *Data { ViewsPkg: viewspkg, Methods: methods, Schemes: schemes, + ServerInterceptors: collectInterceptors(service, methods, scope, true), + ClientInterceptors: collectInterceptors(service, methods, scope, false), Scope: scope, ViewScope: viewScope, errorTypes: errTypes, @@ -779,11 +883,47 @@ func (d ServicesData) analyze(service *expr.ServiceExpr) *Data { viewedResultTypes: viewedRTs, unionValueMethods: unionMethods, } + d[service.Name] = data return data } +// collectInterceptors returns the set of interceptors defined on the given +// service including any interceptor defined on specific service methods or API. +func collectInterceptors(svc *expr.ServiceExpr, methods []*MethodData, scope *codegen.NameScope, server bool) []*InterceptorData { + var ints []*expr.InterceptorExpr + if server { + ints = expr.Root.API.ServerInterceptors + ints = append(ints, svc.ServerInterceptors...) + for _, m := range svc.Methods { + ints = append(ints, m.ServerInterceptors...) + } + } else { + ints = expr.Root.API.ClientInterceptors + ints = append(ints, svc.ClientInterceptors...) + for _, m := range svc.Methods { + ints = append(ints, m.ClientInterceptors...) + } + } + // remove duplicate interceptors + sort.Slice(ints, func(i, j int) bool { + return ints[i].Name < ints[j].Name + }) + for i := 1; i < len(ints); i++ { + if ints[i-1].Name == ints[i].Name { + ints = append(ints[:i], ints[i+1:]...) + i-- + } + } + + res := make([]*InterceptorData, 0, len(ints)) + for _, i := range ints { + res = append(res, buildInterceptorData(svc, methods, i, scope, server)) + } + return res +} + // typeContext returns a contextual attribute for service types. Service types // are Go types and uses non-pointers to hold attributes having default values. func typeContext(pkg string, scope *codegen.NameScope) *codegen.AttributeContext { @@ -1001,14 +1141,15 @@ func buildMethodData(m *expr.MethodExpr, scope *codegen.NameScope) *MethodData { RequestStruct: vname + "RequestData", ResponseStruct: vname + "ResponseData", } - if m.IsStreaming() { - initStreamData(data, m, vname, rname, resultRef, scope) - } + initStreamData(data, m, vname, rname, resultRef, scope) return data } // initStreamData initializes the streaming payload data structures and methods. func initStreamData(data *MethodData, m *expr.MethodExpr, vname, rname, resultRef string, scope *codegen.NameScope) { + if !m.IsStreaming() { + return + } var ( spayloadName string spayloadRef string @@ -1030,24 +1171,28 @@ func initStreamData(data *MethodData, m *expr.MethodExpr, vname, rname, resultRe spayloadEx = m.StreamingPayload.Example(expr.Root.API.ExampleGenerator) } svrStream := &StreamData{ - Interface: vname + "ServerStream", - VarName: scope.Unique(codegen.Goify(m.Name, true), "ServerStream"), - EndpointStruct: vname + "EndpointInput", - Kind: m.Stream, - SendName: "Send", - SendDesc: fmt.Sprintf("Send streams instances of %q.", rname), - SendTypeName: rname, - SendTypeRef: resultRef, - MustClose: true, + Interface: vname + "ServerStream", + VarName: scope.Unique(codegen.Goify(m.Name, true), "ServerStream"), + EndpointStruct: vname + "EndpointInput", + Kind: m.Stream, + SendName: "Send", + SendDesc: fmt.Sprintf("Send streams instances of %q.", rname), + SendWithContextName: "SendWithContext", + SendWithContextDesc: fmt.Sprintf("SendWithContext streams instances of %q with context.", rname), + SendTypeName: rname, + SendTypeRef: resultRef, + MustClose: true, } cliStream := &StreamData{ - Interface: vname + "ClientStream", - VarName: scope.Unique(codegen.Goify(m.Name, true), "ClientStream"), - Kind: m.Stream, - RecvName: "Recv", - RecvDesc: fmt.Sprintf("Recv reads instances of %q from the stream.", rname), - RecvTypeName: rname, - RecvTypeRef: resultRef, + Interface: vname + "ClientStream", + VarName: scope.Unique(codegen.Goify(m.Name, true), "ClientStream"), + Kind: m.Stream, + RecvName: "Recv", + RecvDesc: fmt.Sprintf("Recv reads instances of %q from the stream.", rname), + RecvWithContextName: "RecvWithContext", + RecvWithContextDesc: fmt.Sprintf("RecvWithContext reads instances of %q from the stream with context.", rname), + RecvTypeName: rname, + RecvTypeRef: resultRef, } if m.Stream == expr.ClientStreamKind || m.Stream == expr.BidirectionalStreamKind { switch m.Stream { @@ -1055,9 +1200,13 @@ func initStreamData(data *MethodData, m *expr.MethodExpr, vname, rname, resultRe if resultRef != "" { svrStream.SendName = "SendAndClose" svrStream.SendDesc = fmt.Sprintf("SendAndClose streams instances of %q and closes the stream.", rname) + svrStream.SendWithContextName = "SendAndCloseWithContext" + svrStream.SendWithContextDesc = fmt.Sprintf("SendAndCloseWithContext streams instances of %q and closes the stream with context.", rname) svrStream.MustClose = false cliStream.RecvName = "CloseAndRecv" cliStream.RecvDesc = fmt.Sprintf("CloseAndRecv stops sending messages to the stream and reads instances of %q from the stream.", rname) + cliStream.RecvWithContextName = "CloseAndRecvWithContext" + cliStream.RecvWithContextDesc = fmt.Sprintf("CloseAndRecvWithContext stops sending messages to the stream and reads instances of %q from the stream with context.", rname) } else { cliStream.MustClose = true } @@ -1066,10 +1215,14 @@ func initStreamData(data *MethodData, m *expr.MethodExpr, vname, rname, resultRe } svrStream.RecvName = "Recv" svrStream.RecvDesc = fmt.Sprintf("Recv reads instances of %q from the stream.", spayloadName) + svrStream.RecvWithContextName = "RecvWithContext" + svrStream.RecvWithContextDesc = fmt.Sprintf("RecvWithContext reads instances of %q from the stream with context.", spayloadName) svrStream.RecvTypeName = spayloadName svrStream.RecvTypeRef = spayloadRef cliStream.SendName = "Send" cliStream.SendDesc = fmt.Sprintf("Send streams instances of %q.", spayloadName) + cliStream.SendWithContextName = "SendWithContext" + cliStream.SendWithContextDesc = fmt.Sprintf("SendWithContext streams instances of %q with context.", spayloadName) cliStream.SendTypeName = spayloadName cliStream.SendTypeRef = spayloadRef } @@ -1077,11 +1230,135 @@ func initStreamData(data *MethodData, m *expr.MethodExpr, vname, rname, resultRe data.ServerStream = svrStream data.StreamingPayload = spayloadName data.StreamingPayloadDef = spayloadDef - data.StreamingPayloadRef = spayloadDef + data.StreamingPayloadRef = spayloadRef data.StreamingPayloadDesc = spayloadDesc data.StreamingPayloadEx = spayloadEx } +// buildInterceptorData creates the data needed to generate interceptor code. +func buildInterceptorData(svc *expr.ServiceExpr, methods []*MethodData, i *expr.InterceptorExpr, scope *codegen.NameScope, server bool) *InterceptorData { + data := &InterceptorData{ + Name: codegen.Goify(i.Name, true), + DesignName: i.Name, + Description: i.Description, + } + if len(svc.Methods) == 0 { + return data + } + attributesCollected := false + for _, m := range svc.Methods { + applies := false + intExprs := m.ServerInterceptors + if !server { + intExprs = m.ClientInterceptors + } + for _, in := range intExprs { + if in.Name == i.Name { + if !attributesCollected { + payload, result, streamingPayload := m.Payload, m.Result, m.StreamingPayload + data.ReadPayload = collectAttributes(i.ReadPayload, payload, scope) + data.WritePayload = collectAttributes(i.WritePayload, payload, scope) + data.ReadResult = collectAttributes(i.ReadResult, result, scope) + data.WriteResult = collectAttributes(i.WriteResult, result, scope) + data.ReadStreamingPayload = collectAttributes(i.ReadStreamingPayload, streamingPayload, scope) + data.WriteStreamingPayload = collectAttributes(i.WriteStreamingPayload, streamingPayload, scope) + data.ReadStreamingResult = collectAttributes(i.ReadStreamingResult, result, scope) + data.WriteStreamingResult = collectAttributes(i.WriteStreamingResult, result, scope) + if len(data.ReadPayload) > 0 || len(data.WritePayload) > 0 { + data.HasPayloadAccess = true + } + if len(data.ReadResult) > 0 || len(data.WriteResult) > 0 { + data.HasResultAccess = true + } + if len(data.ReadStreamingPayload) > 0 || len(data.WriteStreamingPayload) > 0 { + data.HasStreamingPayloadAccess = true + } + if len(data.ReadStreamingResult) > 0 || len(data.WriteStreamingResult) > 0 { + data.HasStreamingResultAccess = true + } + attributesCollected = true + } + applies = true + break + } + } + if !applies { + continue + } + var md *MethodData + for _, mt := range methods { + if m.Name == mt.Name { + md = mt + break + } + } + data.Methods = append(data.Methods, buildInterceptorMethodData(i, md)) + if server { + md.ServerInterceptors = append(md.ServerInterceptors, i.Name) + } else { + md.ClientInterceptors = append(md.ClientInterceptors, i.Name) + } + } + return data +} + +// buildInterceptorMethodData creates the data needed to generate interceptor +// method code. +func buildInterceptorMethodData(i *expr.InterceptorExpr, md *MethodData) *MethodInterceptorData { + var serverStream, clientStream *StreamInterceptorData + if md.ServerStream != nil { + serverStream = &StreamInterceptorData{ + Interface: md.ServerStream.Interface, + SendName: md.ServerStream.SendName, + SendWithContextName: md.ServerStream.SendWithContextName, + SendTypeRef: md.ServerStream.SendTypeRef, + RecvName: md.ServerStream.RecvName, + RecvWithContextName: md.ServerStream.RecvWithContextName, + RecvTypeRef: md.ServerStream.RecvTypeRef, + MustClose: md.ServerStream.MustClose, + EndpointStruct: md.ServerStream.EndpointStruct, + } + } + if md.ClientStream != nil { + clientStream = &StreamInterceptorData{ + Interface: md.ClientStream.Interface, + SendName: md.ClientStream.SendName, + SendWithContextName: md.ClientStream.SendWithContextName, + SendTypeRef: md.ClientStream.SendTypeRef, + RecvName: md.ClientStream.RecvName, + RecvWithContextName: md.ClientStream.RecvWithContextName, + RecvTypeRef: md.ClientStream.RecvTypeRef, + MustClose: md.ClientStream.MustClose, + } + } + var payloadAccess, resultAccess, streamingPayloadAccess, streamingResultAccess string + if i.ReadPayload != nil || i.WritePayload != nil { + payloadAccess = codegen.Goify(i.Name, false) + md.VarName + "Payload" + } + if i.ReadResult != nil || i.WriteResult != nil { + resultAccess = codegen.Goify(i.Name, false) + md.VarName + "Result" + } + if i.ReadStreamingPayload != nil || i.WriteStreamingPayload != nil { + streamingPayloadAccess = codegen.Goify(i.Name, false) + md.VarName + "StreamingPayload" + } + if i.ReadStreamingResult != nil || i.WriteStreamingResult != nil { + streamingResultAccess = codegen.Goify(i.Name, false) + md.VarName + "StreamingResult" + } + return &MethodInterceptorData{ + MethodName: md.VarName, + PayloadAccess: payloadAccess, + ResultAccess: resultAccess, + PayloadRef: md.PayloadRef, + ResultRef: md.ResultRef, + StreamingPayloadAccess: streamingPayloadAccess, + StreamingPayloadRef: md.StreamingPayloadRef, + StreamingResultAccess: streamingResultAccess, + StreamingResultRef: md.ResultRef, + ClientStream: clientStream, + ServerStream: serverStream, + } +} + // BuildSchemeData builds the scheme data for the given scheme and method expr. func BuildSchemeData(s *expr.SchemeExpr, m *expr.MethodExpr) *SchemeData { if !expr.IsObject(m.Payload.Type) { @@ -1184,6 +1461,30 @@ func BuildSchemeData(s *expr.SchemeExpr, m *expr.MethodExpr) *SchemeData { return nil } +// collectAttributes builds AttributeData from an AttributeExpr +func collectAttributes(attrNames, parent *expr.AttributeExpr, scope *codegen.NameScope) []*AttributeData { + if attrNames == nil { + return nil + } + obj := expr.AsObject(attrNames.Type) + if obj == nil { + return nil + } + data := make([]*AttributeData, len(*obj)) + for i, nat := range *obj { + parentAttr := parent.Find(nat.Name) + if parentAttr == nil { + continue + } + data[i] = &AttributeData{ + Name: codegen.Goify(nat.Name, true), + TypeRef: scope.GoTypeRef(parentAttr), + Pointer: parent.IsPrimitivePointer(nat.Name, true), + } + } + return data +} + // collectProjectedTypes builds a projected type for every user type found // when recursing through the attributes. The projected types live in the views // package and support the marshaling and unmarshalling of result types that @@ -1300,20 +1601,17 @@ func buildProjectedType(projected, att *expr.AttributeExpr, viewspkg string, sco var ( projections []*InitData typeInits []*InitData - validations []*ValidateData views []*ViewData varname = viewScope.GoTypeName(projected) pt = projected.Type.(expr.UserType) ) - { - if _, isrt := pt.(*expr.ResultTypeExpr); isrt { - typeInits = buildTypeInits(projected, att, viewspkg, scope, viewScope) - projections = buildProjections(projected, att, viewspkg, scope, viewScope) - views = buildViews(att.Type.(*expr.ResultTypeExpr), viewScope) - } - validations = buildValidations(projected, viewScope) + if _, isrt := pt.(*expr.ResultTypeExpr); isrt { + typeInits = buildTypeInits(projected, att, viewspkg, scope, viewScope) + projections = buildProjections(projected, att, viewspkg, scope, viewScope) + views = buildViews(att.Type.(*expr.ResultTypeExpr), viewScope) } + validations := buildValidations(projected, viewScope) removeMeta(projected) return &ProjectedTypeData{ UserTypeData: &UserTypeData{ @@ -1355,115 +1653,94 @@ func buildViews(rt *expr.ResultTypeExpr, viewScope *codegen.NameScope) []*ViewDa // and projected type. func buildViewedResultType(att, projected *expr.AttributeExpr, viewspkg string, scope, viewScope *codegen.NameScope) *ViewedResultTypeData { // collect result type views - var ( - viewName string - views []*ViewData - - rt = att.Type.(*expr.ResultTypeExpr) - isarr = expr.IsArray(att.Type) - ) - { - if !rt.HasMultipleViews() { - viewName = expr.DefaultView - } - if v, ok := att.Meta.Last(expr.ViewMetaKey); ok { - viewName = v - } - views = buildViews(rt, viewScope) + rt := att.Type.(*expr.ResultTypeExpr) + isarr := expr.IsArray(att.Type) + var viewName string + if !rt.HasMultipleViews() { + viewName = expr.DefaultView } + if v, ok := att.Meta.Last(expr.ViewMetaKey); ok { + viewName = v + } + views := buildViews(rt, viewScope) // build validation data - var ( - validate *ValidateData - - resvar = scope.GoTypeName(att) - resref = scope.GoTypeRef(att) - ) - { - data := map[string]any{ - "Projected": scope.GoTypeName(projected), - "ArgVar": "result", - "Source": "result", - "Views": views, - "IsViewed": true, - } - buf := &bytes.Buffer{} - if err := validateTypeCodeTmpl.Execute(buf, data); err != nil { - panic(err) // bug - } - name := "Validate" + resvar - validate = &ValidateData{ - Name: name, - Description: fmt.Sprintf("%s runs the validations defined on the viewed result type %s.", name, resvar), - Ref: resref, - Validate: buf.String(), - } + resvar := scope.GoTypeName(att) + resref := scope.GoTypeRef(att) + data := map[string]any{ + "Projected": scope.GoTypeName(projected), + "ArgVar": "result", + "Source": "result", + "Views": views, + "IsViewed": true, + } + buf := &bytes.Buffer{} + if err := validateTypeCodeTmpl.Execute(buf, data); err != nil { + panic(err) // bug + } + name := "Validate" + resvar + validate := &ValidateData{ + Name: name, + Description: fmt.Sprintf("%s runs the validations defined on the viewed result type %s.", name, resvar), + Ref: resref, + Validate: buf.String(), } // build constructor to initialize viewed result type from result type - var ( - init *InitData - - vresref = viewScope.GoFullTypeRef(att, viewspkg) - ) - { - data := map[string]any{ - "ToViewed": true, - "ArgVar": "res", - "ReturnVar": "vres", - "Views": views, - "ReturnTypeRef": vresref, - "IsCollection": isarr, - "TargetType": scope.GoFullTypeName(att, viewspkg), - "InitName": "new" + viewScope.GoTypeName(projected), - } - buf := &bytes.Buffer{} - if err := initTypeCodeTmpl.Execute(buf, data); err != nil { - panic(err) // bug - } - pkg := "" - if loc := codegen.UserTypeLocation(att.Type); loc != nil { - pkg = loc.PackageName() - } - name := "NewViewed" + resvar - init = &InitData{ - Name: name, - Description: fmt.Sprintf("%s initializes viewed result type %s from result type %s using the given view.", name, resvar, resvar), - Args: []*InitArgData{ - {Name: "res", Ref: scope.GoFullTypeRef(att, pkg)}, - {Name: "view", Ref: "string"}, - }, - ReturnTypeRef: vresref, - Code: buf.String(), - } + vresref := viewScope.GoFullTypeRef(att, viewspkg) + data = map[string]any{ + "ToViewed": true, + "ArgVar": "res", + "ReturnVar": "vres", + "Views": views, + "ReturnTypeRef": vresref, + "IsCollection": isarr, + "TargetType": scope.GoFullTypeName(att, viewspkg), + "InitName": "new" + viewScope.GoTypeName(projected), + } + buf = &bytes.Buffer{} + if err := initTypeCodeTmpl.Execute(buf, data); err != nil { + panic(err) // bug + } + pkg := "" + if loc := codegen.UserTypeLocation(att.Type); loc != nil { + pkg = loc.PackageName() + } + name = "NewViewed" + resvar + init := &InitData{ + Name: name, + Description: fmt.Sprintf("%s initializes viewed result type %s from result type %s using the given view.", name, resvar, resvar), + Args: []*InitArgData{ + {Name: "res", Ref: scope.GoFullTypeRef(att, pkg)}, + {Name: "view", Ref: "string"}, + }, + ReturnTypeRef: vresref, + Code: buf.String(), } // build constructor to initialize result type from viewed result type - var resinit *InitData - { - if loc := codegen.UserTypeLocation(att.Type); loc != nil { - resref = scope.GoFullTypeRef(att, loc.PackageName()) - } - data := map[string]any{ - "ToResult": true, - "ArgVar": "vres", - "ReturnVar": "res", - "Views": views, - "ReturnTypeRef": resref, - "InitName": "new" + scope.GoTypeName(att), - } - buf := &bytes.Buffer{} - if err := initTypeCodeTmpl.Execute(buf, data); err != nil { - panic(err) // bug - } - name := "New" + resvar - resinit = &InitData{ - Name: name, - Description: fmt.Sprintf("%s initializes result type %s from viewed result type %s.", name, resvar, resvar), - Args: []*InitArgData{{Name: "vres", Ref: scope.GoFullTypeRef(att, viewspkg)}}, - ReturnTypeRef: resref, - Code: buf.String(), - } + if loc := codegen.UserTypeLocation(att.Type); loc != nil { + resref = scope.GoFullTypeRef(att, loc.PackageName()) + } + data = map[string]any{ + "ToResult": true, + "ArgVar": "vres", + "ReturnVar": "res", + "Views": views, + "ReturnTypeRef": resref, + "InitName": "new" + scope.GoTypeName(att), + } + buf = &bytes.Buffer{} + if err := initTypeCodeTmpl.Execute(buf, data); err != nil { + panic(err) // bug + } + name = "New" + resvar + resinit := &InitData{ + Name: name, + Description: fmt.Sprintf("%s initializes result type %s from viewed result type %s.", name, resvar, resvar), + Args: []*InitArgData{{Name: "vres", Ref: scope.GoFullTypeRef(att, viewspkg)}}, + ReturnTypeRef: resref, + Code: buf.String(), } projT := wrapProjected(projected.Type.(expr.UserType)) @@ -1526,72 +1803,56 @@ func buildTypeInits(projected, att *expr.AttributeExpr, viewspkg string, scope, // For every view defined in the result type, build a constructor function // to create the result type from a projected type based on the view. - var init []*InitData - { - init = make([]*InitData, 0, len(prt.Views)) - for _, view := range prt.Views { - var ( - typ expr.DataType - - obj = &expr.Object{} - ) - { - walkViewAttrs(pobj, view, func(name string, att, _ *expr.AttributeExpr) { - obj.Set(name, att) - }) - typ = obj - if parr != nil { - typ = &expr.Array{ElemType: &expr.AttributeExpr{ - Type: &expr.ResultTypeExpr{ - UserTypeExpr: &expr.UserTypeExpr{ - AttributeExpr: &expr.AttributeExpr{Type: obj}, - TypeName: scope.GoTypeName(parr.ElemType), - }, - }, - }} - } - } - src := &expr.AttributeExpr{ + init := make([]*InitData, 0, len(prt.Views)) + for _, view := range prt.Views { + var typ expr.DataType + obj := &expr.Object{} + walkViewAttrs(pobj, view, func(name string, att, _ *expr.AttributeExpr) { + obj.Set(name, att) + }) + typ = obj + if parr != nil { + typ = &expr.Array{ElemType: &expr.AttributeExpr{ Type: &expr.ResultTypeExpr{ UserTypeExpr: &expr.UserTypeExpr{ - AttributeExpr: &expr.AttributeExpr{Type: typ}, - TypeName: scope.GoTypeName(projected), + AttributeExpr: &expr.AttributeExpr{Type: obj}, + TypeName: scope.GoTypeName(parr.ElemType), }, - Views: prt.Views, - Identifier: prt.Identifier, }, - } + }} + } + src := &expr.AttributeExpr{ + Type: &expr.ResultTypeExpr{ + UserTypeExpr: &expr.UserTypeExpr{ + AttributeExpr: &expr.AttributeExpr{Type: typ}, + TypeName: scope.GoTypeName(projected), + }, + Views: prt.Views, + Identifier: prt.Identifier, + }, + } - var ( - name string - code string - helpers []*codegen.TransformFunctionData - - srcCtx = projectedTypeContext(viewspkg, true, viewScope) - tgtCtx = typeContext("", scope) - resvar = scope.GoTypeName(att) - ) - { - name = "new" + resvar - if view.Name != expr.DefaultView { - name += codegen.Goify(view.Name, true) - } - code, helpers = buildConstructorCode(src, att, "vres", "res", srcCtx, tgtCtx, view.Name) - } + srcCtx := projectedTypeContext(viewspkg, true, viewScope) + tgtCtx := typeContext("", scope) + resvar := scope.GoTypeName(att) + name := "new" + resvar + if view.Name != expr.DefaultView { + name += codegen.Goify(view.Name, true) + } + code, helpers := buildConstructorCode(src, att, "vres", "res", srcCtx, tgtCtx, view.Name) - pkg := "" - if loc := codegen.UserTypeLocation(att.Type); loc != nil { - pkg = loc.PackageName() - } - init = append(init, &InitData{ - Name: name, - Description: fmt.Sprintf("%s converts projected type %s to service type %s.", name, resvar, resvar), - Args: []*InitArgData{{Name: "vres", Ref: viewScope.GoFullTypeRef(projected, viewspkg)}}, - ReturnTypeRef: scope.GoFullTypeRef(att, pkg), - Code: code, - Helpers: helpers, - }) + pkg := "" + if loc := codegen.UserTypeLocation(att.Type); loc != nil { + pkg = loc.PackageName() } + init = append(init, &InitData{ + Name: name, + Description: fmt.Sprintf("%s converts projected type %s to service type %s.", name, resvar, resvar), + Args: []*InitArgData{{Name: "vres", Ref: viewScope.GoFullTypeRef(projected, viewspkg)}}, + ReturnTypeRef: scope.GoFullTypeRef(att, pkg), + Code: code, + Helpers: helpers, + }) } return init } @@ -1599,40 +1860,30 @@ func buildTypeInits(projected, att *expr.AttributeExpr, viewspkg string, scope, // buildProjections builds the data to generate the constructor code to // project a result type to a projected type based on a view. func buildProjections(projected, att *expr.AttributeExpr, viewspkg string, scope, viewScope *codegen.NameScope) []*InitData { - var ( - projections []*InitData - - rt = att.Type.(*expr.ResultTypeExpr) - ) - - projections = make([]*InitData, 0, len(rt.Views)) + rt := att.Type.(*expr.ResultTypeExpr) + projections := make([]*InitData, 0, len(rt.Views)) for _, view := range rt.Views { - var ( - typ expr.DataType - - obj = &expr.Object{} - ) - { - pobj := expr.AsObject(projected.Type) - parr := expr.AsArray(projected.Type) - if parr != nil { - // result type collection - pobj = expr.AsObject(parr.ElemType.Type) - } - walkViewAttrs(pobj, view, func(name string, att, _ *expr.AttributeExpr) { - obj.Set(name, att) - }) - typ = obj - if parr != nil { - typ = &expr.Array{ElemType: &expr.AttributeExpr{ - Type: &expr.ResultTypeExpr{ - UserTypeExpr: &expr.UserTypeExpr{ - AttributeExpr: &expr.AttributeExpr{Type: obj}, - TypeName: parr.ElemType.Type.Name(), - }, + var typ expr.DataType + obj := &expr.Object{} + pobj := expr.AsObject(projected.Type) + parr := expr.AsArray(projected.Type) + if parr != nil { + // result type collection + pobj = expr.AsObject(parr.ElemType.Type) + } + walkViewAttrs(pobj, view, func(name string, att, _ *expr.AttributeExpr) { + obj.Set(name, att) + }) + typ = obj + if parr != nil { + typ = &expr.Array{ElemType: &expr.AttributeExpr{ + Type: &expr.ResultTypeExpr{ + UserTypeExpr: &expr.UserTypeExpr{ + AttributeExpr: &expr.AttributeExpr{Type: obj}, + TypeName: parr.ElemType.Type.Name(), }, - }} - } + }, + }} } tgt := &expr.AttributeExpr{ Type: &expr.ResultTypeExpr{ @@ -1645,22 +1896,14 @@ func buildProjections(projected, att *expr.AttributeExpr, viewspkg string, scope }, } - var ( - name string - code string - helpers []*codegen.TransformFunctionData - - srcCtx = typeContext("", scope) - tgtCtx = projectedTypeContext(viewspkg, true, viewScope) - tname = scope.GoTypeName(projected) - ) - { - name = "new" + tname - if view.Name != expr.DefaultView { - name += codegen.Goify(view.Name, true) - } - code, helpers = buildConstructorCode(att, tgt, "res", "vres", srcCtx, tgtCtx, view.Name) + srcCtx := typeContext("", scope) + tgtCtx := projectedTypeContext(viewspkg, true, viewScope) + tname := scope.GoTypeName(projected) + name := "new" + tname + if view.Name != expr.DefaultView { + name += codegen.Goify(view.Name, true) } + code, helpers := buildConstructorCode(att, tgt, "res", "vres", srcCtx, tgtCtx, view.Name) pkg := "" if loc := codegen.UserTypeLocation(att.Type); loc != nil { @@ -1681,12 +1924,9 @@ func buildProjections(projected, att *expr.AttributeExpr, viewspkg string, scope // buildValidations builds the data required to generate validations for the // projected types. func buildValidations(projected *expr.AttributeExpr, scope *codegen.NameScope) []*ValidateData { - var ( - validations []*ValidateData - - ut = projected.Type.(expr.UserType) - tname = scope.GoTypeName(projected) - ) + ut := projected.Type.(expr.UserType) + tname := scope.GoTypeName(projected) + var validations []*ValidateData if rt, isrt := ut.(*expr.ResultTypeExpr); isrt { // for result types we create a validation function containing view // specific validation logic for each view @@ -1698,16 +1938,11 @@ func buildValidations(projected *expr.AttributeExpr, scope *codegen.NameScope) [ "Source": "result", "IsCollection": arr != nil, } - var ( - name string - vn string - ) - { - name = "Validate" + tname - if view.Name != expr.DefaultView { - vn = codegen.Goify(view.Name, true) - name += vn - } + var vn string + name := "Validate" + tname + if view.Name != expr.DefaultView { + vn = codegen.Goify(view.Name, true) + name += vn } if arr != nil { @@ -1715,32 +1950,26 @@ func buildValidations(projected *expr.AttributeExpr, scope *codegen.NameScope) [ data["Source"] = "item" data["ValidateVar"] = "Validate" + scope.GoTypeName(arr.ElemType) + vn } else { - var ( - ctx *codegen.AttributeContext - fields []map[string]any - - o = &expr.Object{} - ) - { - walkViewAttrs(expr.AsObject(projected.Type), view, func(name string, attr, vatt *expr.AttributeExpr) { - if rt, ok := attr.Type.(*expr.ResultTypeExpr); ok { - // use explicitly specified view (if any) for the attribute, - // otherwise use default - vw := "" - if v, ok := vatt.Meta.Last(expr.ViewMetaKey); ok && v != expr.DefaultView { - vw = v - } - fields = append(fields, map[string]any{ - "Name": name, - "ValidateVar": "Validate" + scope.GoTypeName(attr) + codegen.Goify(vw, true), - "IsRequired": rt.Attribute().IsRequired(name), - }) - } else { - o.Set(name, attr) + var fields []map[string]any + o := &expr.Object{} + walkViewAttrs(expr.AsObject(projected.Type), view, func(name string, attr, vatt *expr.AttributeExpr) { + if rt, ok := attr.Type.(*expr.ResultTypeExpr); ok { + // use explicitly specified view (if any) for the attribute, + // otherwise use default + vw := "" + if v, ok := vatt.Meta.Last(expr.ViewMetaKey); ok && v != expr.DefaultView { + vw = v } - }) - ctx = projectedTypeContext("", !expr.IsPrimitive(projected.Type), scope) - } + fields = append(fields, map[string]any{ + "Name": name, + "ValidateVar": "Validate" + scope.GoTypeName(attr) + codegen.Goify(vw, true), + "IsRequired": rt.Attribute().IsRequired(name), + }) + } else { + o.Set(name, attr) + } + }) + ctx := projectedTypeContext("", !expr.IsPrimitive(projected.Type), scope) data["Validate"] = codegen.ValidationCode(&expr.AttributeExpr{Type: o, Validation: rt.Validation}, rt, ctx, true, false, true, "result") data["Fields"] = fields } @@ -1822,15 +2051,10 @@ func buildConstructorCode(src, tgt *expr.AttributeExpr, sourceVar, targetVar str data["Source"] = sourceVar data["Target"] = targetVar - var ( - code string - err error - ) - { - // build code for target with no result types - if code, helpers, err = codegen.GoTransform(src, tatt, sourceVar, targetVar, sourceCtx, targetCtx, "transform", true); err != nil { - panic(err) // bug - } + // build code for target with no result types + code, helpers, err := codegen.GoTransform(src, tatt, sourceVar, targetVar, sourceCtx, targetCtx, "transform", true) + if err != nil { + panic(err) // bug } data["Code"] = code @@ -1876,7 +2100,7 @@ func walkViewAttrs(obj *expr.Object, view *expr.ViewExpr, walker func(name strin } // removeMeta removes the meta attributes from the given attribute. This is -// needed to make sure that any field name overridding is removed when +// needed to make sure that any field name overriding is removed when // generating protobuf types (as protogen itself won't honor these overrides). func removeMeta(att *expr.AttributeExpr) { _ = codegen.Walk(att, func(a *expr.AttributeExpr) error { diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/client_interceptor_stream_wrapper_types.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/client_interceptor_stream_wrapper_types.go.tpl new file mode 100644 index 0000000000..9a250d08f6 --- /dev/null +++ b/vendor/goa.design/goa/v3/codegen/service/templates/client_interceptor_stream_wrapper_types.go.tpl @@ -0,0 +1,14 @@ +{{- range .WrappedClientStreams }} + +{{ comment (printf "wrapped%s is a client interceptor wrapper for the %s stream." .Interface .Interface) }} +type wrapped{{ .Interface }} struct { + ctx context.Context + {{- if ne .SendTypeRef "" }} + sendWithContext func(context.Context, {{ .SendTypeRef }}) error + {{- end }} + {{- if ne .RecvTypeRef "" }} + recvWithContext func(context.Context) ({{ .RecvTypeRef }}, error) + {{- end }} + stream {{ .Interface }} +} +{{- end }} diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/client_interceptor_stream_wrappers.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/client_interceptor_stream_wrappers.go.tpl new file mode 100644 index 0000000000..e1f3e2c5a2 --- /dev/null +++ b/vendor/goa.design/goa/v3/codegen/service/templates/client_interceptor_stream_wrappers.go.tpl @@ -0,0 +1,40 @@ +{{- range .WrappedClientStreams }} + + {{- if ne .SendTypeRef "" }} + +{{ comment (printf "%s streams instances of \"%s\" after executing the applied interceptor." .SendName .Interface) }} +func (w *wrapped{{ .Interface }}) {{ .SendName }}(v {{ .SendTypeRef }}) error { + return w.SendWithContext(w.ctx, v) +} + +{{ comment (printf "%s streams instances of \"%s\" after executing the applied interceptor with context." .SendWithContextName .Interface) }} +func (w *wrapped{{ .Interface }}) {{ .SendWithContextName }}(ctx context.Context, v {{ .SendTypeRef }}) error { + if w.sendWithContext == nil { + return w.stream.{{ .SendWithContextName }}(ctx, v) + } + return w.sendWithContext(ctx, v) +} + {{- end }} + {{- if ne .RecvTypeRef "" }} + +{{ comment (printf "%s reads instances of \"%s\" from the stream after executing the applied interceptor." .RecvName .Interface) }} +func (w *wrapped{{ .Interface }}) {{ .RecvName }}() ({{ .RecvTypeRef }}, error) { + return w.RecvWithContext(w.ctx) +} + +{{ comment (printf "%s reads instances of \"%s\" from the stream after executing the applied interceptor with context." .RecvWithContextName .Interface) }} +func (w *wrapped{{ .Interface }}) {{ .RecvWithContextName }}(ctx context.Context) ({{ .RecvTypeRef }}, error) { + if w.recvWithContext == nil { + return w.stream.{{ .RecvWithContextName }}(ctx) + } + return w.recvWithContext(ctx) +} + {{- end }} + {{- if .MustClose }} + +// Close closes the stream. +func (w *wrapped{{ .Interface }}) Close() error { + return w.stream.Close() +} + {{- end }} +{{- end }} diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/client_interceptor_wrappers.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/client_interceptor_wrappers.go.tpl new file mode 100644 index 0000000000..c01590d59c --- /dev/null +++ b/vendor/goa.design/goa/v3/codegen/service/templates/client_interceptor_wrappers.go.tpl @@ -0,0 +1,69 @@ +{{- range .ClientInterceptors }} +{{- $interceptor := . }} +{{- range .Methods }} + +{{ comment (printf "wrapClient%s%s applies the %s client interceptor to endpoints." $interceptor.Name .MethodName $interceptor.DesignName) }} +func wrapClient{{ .MethodName }}{{ $interceptor.Name }}(endpoint goa.Endpoint, i ClientInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + {{- if or $interceptor.HasStreamingPayloadAccess $interceptor.HasStreamingResultAccess }} + {{- if $interceptor.HasPayloadAccess }} + info := &{{ $interceptor.Name }}Info{ + service: "{{ $.Service }}", + method: "{{ .MethodName }}", + callType: goa.InterceptorUnary, + rawPayload: req, + } + res, err := i.{{ $interceptor.Name }}(ctx, info, endpoint) + {{- else }} + res, err := endpoint(ctx, req) + {{- end }} + if err != nil { + return res, err + } + stream := res.({{ .ClientStream.Interface }}) + return &wrapped{{ .ClientStream.Interface }}{ + ctx: ctx, + {{- if $interceptor.HasStreamingPayloadAccess }} + sendWithContext: func(ctx context.Context, req {{ .ClientStream.SendTypeRef }}) error { + info := &{{ $interceptor.Name }}Info{ + service: "{{ $.Service }}", + method: "{{ .MethodName }}", + callType: goa.InterceptorStreamingSend, + rawPayload: req, + } + _, err := i.{{ $interceptor.Name }}(ctx, info, func(ctx context.Context, req any) (any, error) { + castReq, _ := req.({{ .ClientStream.SendTypeRef }}) + return nil, stream.{{ .ClientStream.SendWithContextName }}(ctx, castReq) + }) + return err + }, + {{- end }} + {{- if $interceptor.HasStreamingResultAccess }} + recvWithContext: func(ctx context.Context) ({{ .ClientStream.RecvTypeRef }}, error) { + info := &{{ $interceptor.Name }}Info{ + service: "{{ $.Service }}", + method: "{{ .MethodName }}", + callType: goa.InterceptorStreamingRecv, + } + res, err := i.{{ $interceptor.Name }}(ctx, info, func(ctx context.Context, _ any) (any, error) { + return stream.{{ .ClientStream.RecvWithContextName }}(ctx) + }) + castRes, _ := res.({{ .ClientStream.RecvTypeRef }}) + return castRes, err + }, + {{- end }} + stream: stream, + }, nil + {{- else }} + info := &{{ $interceptor.Name }}Info{ + service: "{{ $.Service }}", + method: "{{ .MethodName }}", + callType: goa.InterceptorUnary, + rawPayload: req, + } + return i.{{ $interceptor.Name }}(ctx, info, endpoint) + {{- end }} + } +} +{{- end }} +{{- end }} diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/client_interceptors.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/client_interceptors.go.tpl new file mode 100644 index 0000000000..9528e3d123 --- /dev/null +++ b/vendor/goa.design/goa/v3/codegen/service/templates/client_interceptors.go.tpl @@ -0,0 +1,12 @@ +// ClientInterceptors defines the interface for all client-side interceptors. +// Client interceptors execute after the payload is encoded and before the request +// is sent to the server. The implementation is responsible for calling next to +// complete the request. +type ClientInterceptors interface { +{{- range .ClientInterceptors }} +{{- if .Description }} + {{ comment .Description }} +{{- end }} + {{ .Name }}(ctx context.Context, info *{{ .Name }}Info, next goa.Endpoint) (any, error) +{{- end }} +} diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/client_wrappers.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/client_wrappers.go.tpl new file mode 100644 index 0000000000..711e632e72 --- /dev/null +++ b/vendor/goa.design/goa/v3/codegen/service/templates/client_wrappers.go.tpl @@ -0,0 +1,8 @@ + +{{ comment (printf "Wrap%sClientEndpoint wraps the %s endpoint with the client interceptors defined in the design." .MethodVarName .Method) }} +func Wrap{{ .MethodVarName }}ClientEndpoint(endpoint goa.Endpoint, i ClientInterceptors) goa.Endpoint { + {{- range .Interceptors }} + endpoint = wrapClient{{ $.MethodVarName }}{{ . }}(endpoint, i) + {{- end }} + return endpoint +} diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/endpoint_wrappers.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/endpoint_wrappers.go.tpl new file mode 100644 index 0000000000..deffd14fc9 --- /dev/null +++ b/vendor/goa.design/goa/v3/codegen/service/templates/endpoint_wrappers.go.tpl @@ -0,0 +1,7 @@ +{{ comment (printf "Wrap%sEndpoint wraps the %s endpoint with the server-side interceptors defined in the design." .MethodVarName .Method) }} +func Wrap{{ .MethodVarName }}Endpoint(endpoint goa.Endpoint, i ServerInterceptors) goa.Endpoint { + {{- range .Interceptors }} + endpoint = wrap{{ $.MethodVarName }}{{ . }}(endpoint, i) + {{- end }} + return endpoint +} diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/example_client_interceptor.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/example_client_interceptor.go.tpl new file mode 100644 index 0000000000..4dad48f184 --- /dev/null +++ b/vendor/goa.design/goa/v3/codegen/service/templates/example_client_interceptor.go.tpl @@ -0,0 +1,24 @@ +// {{ .StructName }}ClientInterceptors implements the client interceptors for the {{ .ServiceName }} service. +type {{ .StructName }}ClientInterceptors struct { +} + +// New{{ .StructName }}ClientInterceptors creates a new client interceptor for the {{ .ServiceName }} service. +func New{{ .StructName }}ClientInterceptors() *{{ .StructName }}ClientInterceptors { + return &{{ .StructName }}ClientInterceptors{} +} + +{{- range .ClientInterceptors }} +{{- if .Description }} +{{ comment .Description }} +{{- end }} +func (i *{{ $.StructName }}ClientInterceptors) {{ .Name }}(ctx context.Context, info *{{ $.PkgName }}.{{ .Name }}Info, next goa.Endpoint) (any, error) { + log.Printf(ctx, "[{{ .Name }}] Sending request: %v", info.RawPayload()) + resp, err := next(ctx, info.RawPayload()) + if err != nil { + log.Printf(ctx, "[{{ .Name }}] Error: %v", err) + return nil, err + } + log.Printf(ctx, "[{{ .Name }}] Received response: %v", resp) + return resp, nil +} +{{- end }} diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/security_authfuncs.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/example_security_authfuncs.go.tpl similarity index 100% rename from vendor/goa.design/goa/v3/codegen/service/templates/security_authfuncs.go.tpl rename to vendor/goa.design/goa/v3/codegen/service/templates/example_security_authfuncs.go.tpl diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/example_server_interceptor.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/example_server_interceptor.go.tpl new file mode 100644 index 0000000000..9e1ed5086e --- /dev/null +++ b/vendor/goa.design/goa/v3/codegen/service/templates/example_server_interceptor.go.tpl @@ -0,0 +1,24 @@ +// {{ .StructName }}ServerInterceptors implements the server interceptor for the {{ .ServiceName }} service. +type {{ .StructName }}ServerInterceptors struct { +} + +// New{{ .StructName }}ServerInterceptors creates a new server interceptor for the {{ .ServiceName }} service. +func New{{ .StructName }}ServerInterceptors() *{{ .StructName }}ServerInterceptors { + return &{{ .StructName }}ServerInterceptors{} +} + +{{- range .ServerInterceptors }} +{{- if .Description }} +{{ comment .Description }} +{{- end }} +func (i *{{ $.StructName }}ServerInterceptors) {{ .Name }}(ctx context.Context, info *{{ $.PkgName }}.{{ .Name }}Info, next goa.Endpoint) (any, error) { + log.Printf(ctx, "[{{ .Name }}] Processing request: %v", info.RawPayload()) + resp, err := next(ctx, info.RawPayload()) + if err != nil { + log.Printf(ctx, "[{{ .Name }}] Error: %v", err) + return nil, err + } + log.Printf(ctx, "[{{ .Name }}] Response: %v", resp) + return resp, nil +} +{{- end }} diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/service_init.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/example_service_init.go.tpl similarity index 100% rename from vendor/goa.design/goa/v3/codegen/service/templates/service_init.go.tpl rename to vendor/goa.design/goa/v3/codegen/service/templates/example_service_init.go.tpl diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/service_struct.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/example_service_struct.go.tpl similarity index 100% rename from vendor/goa.design/goa/v3/codegen/service/templates/service_struct.go.tpl rename to vendor/goa.design/goa/v3/codegen/service/templates/example_service_struct.go.tpl diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/interceptors.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/interceptors.go.tpl new file mode 100644 index 0000000000..8c53dbb773 --- /dev/null +++ b/vendor/goa.design/goa/v3/codegen/service/templates/interceptors.go.tpl @@ -0,0 +1,254 @@ +// Public accessor methods for Info types +{{- range . }} + +// Service returns the name of the service handling the request. +func (info *{{ .Name }}Info) Service() string { + return info.service +} + +// Method returns the name of the method handling the request. +func (info *{{ .Name }}Info) Method() string { + return info.method +} + +// CallType returns the type of call the interceptor is handling. +func (info *{{ .Name }}Info) CallType() goa.InterceptorCallType { + return info.callType +} + +// RawPayload returns the raw payload of the request. +func (info *{{ .Name }}Info) RawPayload() any { + return info.rawPayload +} + {{- if .HasPayloadAccess }} + +// Payload returns a type-safe accessor for the method payload. +func (info *{{ .Name }}Info) Payload() {{ .Name }}Payload { + {{- if gt (len .Methods) 1 }} + switch info.Method() { + {{- range .Methods }} + case "{{ .MethodName }}": + {{- if hasEndpointStruct . }} + switch pay := info.RawPayload().(type) { + case *{{ .ServerStream.EndpointStruct }}: + return &{{ .PayloadAccess }}{payload: pay.Payload} + default: + return &{{ .PayloadAccess }}{payload: pay.({{ .PayloadRef }})} + } + {{- else }} + return &{{ .PayloadAccess }}{payload: info.RawPayload().({{ .PayloadRef }})} + {{- end }} + {{- end }} + default: + return nil + } + {{- else }} + {{- if hasEndpointStruct (index .Methods 0) }} + switch pay := info.RawPayload().(type) { + case *{{ (index .Methods 0).ServerStream.EndpointStruct }}: + return &{{ (index .Methods 0).PayloadAccess }}{payload: pay.Payload} + default: + return &{{ (index .Methods 0).PayloadAccess }}{payload: pay.({{ (index .Methods 0).PayloadRef }})} + } + {{- else }} + return &{{ (index .Methods 0).PayloadAccess }}{payload: info.RawPayload().({{ (index .Methods 0).PayloadRef }})} + {{- end }} + {{- end }} +} + {{- end }} + + {{- if .HasResultAccess }} +// Result returns a type-safe accessor for the method result. +func (info *{{ .Name }}Info) Result(res any) {{ .Name }}Result { + {{- if gt (len .Methods) 1 }} + switch info.Method() { + {{- range .Methods }} + case "{{ .MethodName }}": + return &{{ .ResultAccess }}{result: res.({{ .ResultRef }})} + {{- end }} + default: + return nil + } + {{- else }} + return &{{ (index .Methods 0).ResultAccess }}{result: res.({{ (index .Methods 0).ResultRef }})} + {{- end }} +} + {{- end }} + + {{- if .HasStreamingPayloadAccess }} +// ClientStreamingPayload returns a type-safe accessor for the method streaming payload for a client-side interceptor. +func (info *{{ .Name }}Info) ClientStreamingPayload() {{ .Name }}StreamingPayload { + {{- if gt (len .Methods) 1 }} + switch info.Method() { + {{- range .Methods }} + case "{{ .MethodName }}": + return &{{ .StreamingPayloadAccess }}{payload: info.RawPayload().({{ .StreamingPayloadRef }})} + {{- end }} + default: + return nil + } + {{- else }} + return &{{ (index .Methods 0).StreamingPayloadAccess }}{payload: info.RawPayload().({{ (index .Methods 0).StreamingPayloadRef }})} + {{- end }} +} + {{- end }} + + {{- if .HasStreamingResultAccess }} +// ClientStreamingResult returns a type-safe accessor for the method streaming result for a client-side interceptor. +func (info *{{ .Name }}Info) ClientStreamingResult(res any) {{ .Name }}StreamingResult { + {{- if gt (len .Methods) 1 }} + switch info.Method() { + {{- range .Methods }} + case "{{ .MethodName }}": + return &{{ .StreamingResultAccess }}{result: res.({{ .StreamingResultRef }})} + {{- end }} + default: + return nil + } + {{- else }} + return &{{ (index .Methods 0).StreamingResultAccess }}{result: res.({{ (index .Methods 0).StreamingResultRef }})} + {{- end }} +} + {{- end }} + + {{- if .HasStreamingPayloadAccess }} +// ServerStreamingPayload returns a type-safe accessor for the method streaming payload for a server-side interceptor. +func (info *{{ .Name }}Info) ServerStreamingPayload(pay any) {{ .Name }}StreamingPayload { + {{- if gt (len .Methods) 1 }} + switch info.Method() { + {{- range .Methods }} + case "{{ .MethodName }}": + return &{{ .StreamingPayloadAccess }}{payload: pay.({{ .StreamingPayloadRef }})} + {{- end }} + default: + return nil + } + {{- else }} + return &{{ (index .Methods 0).StreamingPayloadAccess }}{payload: pay.({{ (index .Methods 0).StreamingPayloadRef }})} + {{- end }} +} + {{- end }} + + {{- if .HasStreamingResultAccess }} +// ServerStreamingResult returns a type-safe accessor for the method streaming result for a server-side interceptor. +func (info *{{ .Name }}Info) ServerStreamingResult() {{ .Name }}StreamingResult { + {{- if gt (len .Methods) 1 }} + switch info.Method() { + {{- range .Methods }} + case "{{ .MethodName }}": + return &{{ .StreamingResultAccess }}{result: info.RawPayload().({{ .StreamingResultRef }})} + {{- end }} + default: + return nil + } + {{- else }} + return &{{ (index .Methods 0).StreamingResultAccess }}{result: info.RawPayload().({{ (index .Methods 0).StreamingResultRef }})} + {{- end }} +} + {{- end }} +{{- end }} + +{{- if hasPrivateImplementationTypes . }} +// Private implementation methods +{{- range . }} + {{ $interceptor := . }} + {{- range .Methods }} + {{- $method := . }} + {{- range $interceptor.ReadPayload }} +func (p *{{ $method.PayloadAccess }}) {{ .Name }}() {{ .TypeRef }} { + {{- if .Pointer }} + if p.payload.{{ .Name }} == nil { + var zero {{ .TypeRef }} + return zero + } + return *p.payload.{{ .Name }} + {{- else }} + return p.payload.{{ .Name }} + {{- end }} +} + {{- end }} + + {{- range $interceptor.WritePayload }} +func (p *{{ $method.PayloadAccess }}) Set{{ .Name }}(v {{ .TypeRef }}) { + {{- if .Pointer }} + p.payload.{{ .Name }} = &v + {{- else }} + p.payload.{{ .Name }} = v + {{- end }} +} + {{- end }} + + {{- range $interceptor.ReadResult }} +func (r *{{ $method.ResultAccess }}) {{ .Name }}() {{ .TypeRef }} { + {{- if .Pointer }} + if r.result.{{ .Name }} == nil { + var zero {{ .TypeRef }} + return zero + } + return *r.result.{{ .Name }} + {{- else }} + return r.result.{{ .Name }} + {{- end }} +} + {{- end }} + + {{- range $interceptor.WriteResult }} +func (r *{{ $method.ResultAccess }}) Set{{ .Name }}(v {{ .TypeRef }}) { + {{- if .Pointer }} + r.result.{{ .Name }} = &v + {{- else }} + r.result.{{ .Name }} = v + {{- end }} +} + {{- end }} + + {{- range $interceptor.ReadStreamingPayload }} +func (p *{{ $method.StreamingPayloadAccess }}) {{ .Name }}() {{ .TypeRef }} { + {{- if .Pointer }} + if p.payload.{{ .Name }} == nil { + var zero {{ .TypeRef }} + return zero + } + return *p.payload.{{ .Name }} + {{- else }} + return p.payload.{{ .Name }} + {{- end }} +} + {{- end }} + + {{- range $interceptor.WriteStreamingPayload }} +func (p *{{ $method.StreamingPayloadAccess }}) Set{{ .Name }}(v {{ .TypeRef }}) { + {{- if .Pointer }} + p.payload.{{ .Name }} = &v + {{- else }} + p.payload.{{ .Name }} = v + {{- end }} +} + {{- end }} + + {{- range $interceptor.ReadStreamingResult }} +func (r *{{ $method.StreamingResultAccess }}) {{ .Name }}() {{ .TypeRef }} { + {{- if .Pointer }} + if r.result.{{ .Name }} == nil { + var zero {{ .TypeRef }} + return zero + } + return *r.result.{{ .Name }} + {{- else }} + return r.result.{{ .Name }} + {{- end }} +} + {{- end }} + + {{- range $interceptor.WriteStreamingResult }} +func (r *{{ $method.StreamingResultAccess }}) Set{{ .Name }}(v {{ .TypeRef }}) { + {{- if .Pointer }} + r.result.{{ .Name }} = &v + {{- else }} + r.result.{{ .Name }} = v + {{- end }} +} + {{- end }} + {{- end }} +{{- end }} +{{- end }} diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/interceptors_types.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/interceptors_types.go.tpl new file mode 100644 index 0000000000..10b890f470 --- /dev/null +++ b/vendor/goa.design/goa/v3/codegen/service/templates/interceptors_types.go.tpl @@ -0,0 +1,115 @@ + +// Access interfaces for interceptor payloads and results +type ( +{{- range . }} + // {{ .Name }}Info provides metadata about the current interception. + // It includes service name, method name, and access to the endpoint. + {{ .Name }}Info struct { + service string + method string + callType goa.InterceptorCallType + rawPayload any + } + {{- if .HasPayloadAccess }} + + // {{ .Name }}Payload provides type-safe access to the method payload. + // It allows reading and writing specific fields of the payload as defined + // in the design. + {{ .Name }}Payload interface { + {{- range .ReadPayload }} + {{ .Name }}() {{ .TypeRef }} + {{- end }} + {{- range .WritePayload }} + Set{{ .Name }}({{ .TypeRef }}) + {{- end }} + } + {{- end }} + {{- if .HasResultAccess }} + + // {{ .Name }}Result provides type-safe access to the method result. + // It allows reading and writing specific fields of the result as defined + // in the design. + {{ .Name }}Result interface { + {{- range .ReadResult }} + {{ .Name }}() {{ .TypeRef }} + {{- end }} + {{- range .WriteResult }} + Set{{ .Name }}({{ .TypeRef }}) + {{- end }} + } + {{- end }} + {{- if .HasStreamingPayloadAccess }} + + // {{ .Name }}StreamingPayload provides type-safe access to the method streaming payload. + // It allows reading and writing specific fields of the streaming payload as defined + // in the design. + {{ .Name }}StreamingPayload interface { + {{- range .ReadStreamingPayload }} + {{ .Name }}() {{ .TypeRef }} + {{- end }} + {{- range .WriteStreamingPayload }} + Set{{ .Name }}({{ .TypeRef }}) + {{- end }} + } + {{- end }} + {{- if .HasStreamingResultAccess }} + + // {{ .Name }}StreamingResult provides type-safe access to the method streaming result. + // It allows reading and writing specific fields of the streaming result as defined + // in the design. + {{ .Name }}StreamingResult interface { + {{- range .ReadStreamingResult }} + {{ .Name }}() {{ .TypeRef }} + {{- end }} + {{- range .WriteStreamingResult }} + Set{{ .Name }}({{ .TypeRef }}) + {{- end }} + } + {{- end }} +{{- end }} +) +{{- if hasPrivateImplementationTypes . }} + +// Private implementation types +type ( + {{- range . }} + {{- range .Methods }} + {{- if .PayloadAccess }} + {{ .PayloadAccess }} struct { + payload {{ .PayloadRef }} + } + {{- end }} + {{- end }} + {{- end }} + + {{- range . }} + {{- range .Methods }} + {{- if .ResultAccess }} + {{ .ResultAccess }} struct { + result {{ .ResultRef }} + } + {{- end }} + {{- end }} + {{- end }} + + {{- range . }} + {{- range .Methods }} + {{- if .StreamingPayloadAccess }} + {{ .StreamingPayloadAccess }} struct { + payload {{ .StreamingPayloadRef }} + } + {{- end }} + {{- end }} + {{- end }} + + {{- range . }} + {{- range .Methods }} + {{- if .StreamingResultAccess }} + {{ .StreamingResultAccess }} struct { + result {{ .StreamingResultRef }} + } + {{- end }} + {{- end }} + {{- end }} +) +{{- end }} diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/server_interceptor_stream_wrapper_types.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/server_interceptor_stream_wrapper_types.go.tpl new file mode 100644 index 0000000000..a33a45fa2a --- /dev/null +++ b/vendor/goa.design/goa/v3/codegen/service/templates/server_interceptor_stream_wrapper_types.go.tpl @@ -0,0 +1,14 @@ +{{- range .WrappedServerStreams }} + +{{ comment (printf "wrapped%s is a server interceptor wrapper for the %s stream." .Interface .Interface) }} +type wrapped{{ .Interface }} struct { + ctx context.Context + {{- if ne .SendTypeRef "" }} + sendWithContext func(context.Context, {{ .SendTypeRef }}) error + {{- end }} + {{- if ne .RecvTypeRef "" }} + recvWithContext func(context.Context) ({{ .RecvTypeRef }}, error) + {{- end }} + stream {{ .Interface }} +} +{{- end }} diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/server_interceptor_stream_wrappers.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/server_interceptor_stream_wrappers.go.tpl new file mode 100644 index 0000000000..f07af48ca7 --- /dev/null +++ b/vendor/goa.design/goa/v3/codegen/service/templates/server_interceptor_stream_wrappers.go.tpl @@ -0,0 +1,40 @@ +{{- range .WrappedServerStreams }} + + {{- if ne .SendTypeRef "" }} + +{{ comment (printf "%s streams instances of \"%s\" after executing the applied interceptor." .SendName .Interface) }} +func (w *wrapped{{ .Interface }}) {{ .SendName }}(v {{ .SendTypeRef }}) error { + return w.SendWithContext(w.ctx, v) +} + +{{ comment (printf "%s streams instances of \"%s\" after executing the applied interceptor with context." .SendWithContextName .Interface) }} +func (w *wrapped{{ .Interface }}) {{ .SendWithContextName }}(ctx context.Context, v {{ .SendTypeRef }}) error { + if w.sendWithContext == nil { + return w.stream.{{ .SendWithContextName }}(ctx, v) + } + return w.sendWithContext(ctx, v) +} + {{- end }} + {{- if ne .RecvTypeRef "" }} + +{{ comment (printf "%s reads instances of \"%s\" from the stream after executing the applied interceptor." .RecvName .Interface) }} +func (w *wrapped{{ .Interface }}) {{ .RecvName }}() ({{ .RecvTypeRef }}, error) { + return w.RecvWithContext(w.ctx) +} + +{{ comment (printf "%s reads instances of \"%s\" from the stream after executing the applied interceptor with context." .RecvWithContextName .Interface) }} +func (w *wrapped{{ .Interface }}) {{ .RecvWithContextName }}(ctx context.Context) ({{ .RecvTypeRef }}, error) { + if w.recvWithContext == nil { + return w.stream.{{ .RecvWithContextName }}(ctx) + } + return w.recvWithContext(ctx) +} + {{- end }} + {{- if .MustClose }} + +// Close closes the stream. +func (w *wrapped{{ .Interface }}) Close() error { + return w.stream.Close() +} + {{- end }} +{{- end }} diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/server_interceptor_wrappers.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/server_interceptor_wrappers.go.tpl new file mode 100644 index 0000000000..0dac75a6a7 --- /dev/null +++ b/vendor/goa.design/goa/v3/codegen/service/templates/server_interceptor_wrappers.go.tpl @@ -0,0 +1,66 @@ +{{- range .ServerInterceptors }} +{{- $interceptor := . }} +{{- range .Methods }} + +{{ comment (printf "wrap%s%s applies the %s server interceptor to endpoints." $interceptor.Name .MethodName $interceptor.DesignName) }} +func wrap{{ .MethodName }}{{ $interceptor.Name }}(endpoint goa.Endpoint, i ServerInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + {{- if or $interceptor.HasStreamingPayloadAccess $interceptor.HasStreamingResultAccess }} + stream := req.(*{{ .ServerStream.EndpointStruct }}).Stream + req.(*{{ .ServerStream.EndpointStruct }}).Stream = &wrapped{{ .ServerStream.Interface }}{ + ctx: ctx, + {{- if $interceptor.HasStreamingResultAccess }} + sendWithContext: func(ctx context.Context, req {{ .ServerStream.SendTypeRef }}) error { + info := &{{ $interceptor.Name }}Info{ + service: "{{ $.Service }}", + method: "{{ .MethodName }}", + callType: goa.InterceptorStreamingSend, + rawPayload: req, + } + _, err := i.{{ $interceptor.Name }}(ctx, info, func(ctx context.Context, req any) (any, error) { + castReq, _ := req.({{ .ServerStream.SendTypeRef }}) + return nil, stream.{{ .ServerStream.SendWithContextName }}(ctx, castReq) + }) + return err + }, + {{- end }} + {{- if $interceptor.HasStreamingPayloadAccess }} + recvWithContext: func(ctx context.Context) ({{ .ServerStream.RecvTypeRef }}, error) { + info := &{{ $interceptor.Name }}Info{ + service: "{{ $.Service }}", + method: "{{ .MethodName }}", + callType: goa.InterceptorStreamingRecv, + } + res, err := i.{{ $interceptor.Name }}(ctx, info, func(ctx context.Context, _ any) (any, error) { + return stream.{{ .ServerStream.RecvWithContextName }}(ctx) + }) + castRes, _ := res.({{ .ServerStream.RecvTypeRef }}) + return castRes, err + }, + {{- end }} + stream: stream, + } + {{- if $interceptor.HasPayloadAccess }} + info := &{{ $interceptor.Name }}Info{ + service: "{{ $.Service }}", + method: "{{ .MethodName }}", + callType: goa.InterceptorUnary, + rawPayload: req, + } + return i.{{ $interceptor.Name }}(ctx, info, endpoint) + {{- else }} + return endpoint(ctx, req) + {{- end }} + {{- else }} + info := &{{ $interceptor.Name }}Info{ + service: "{{ $.Service }}", + method: "{{ .MethodName }}", + callType: goa.InterceptorUnary, + rawPayload: req, + } + return i.{{ $interceptor.Name }}(ctx, info, endpoint) + {{- end }} + } +} +{{- end }} +{{- end }} diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/server_interceptors.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/server_interceptors.go.tpl new file mode 100644 index 0000000000..3bd263dc95 --- /dev/null +++ b/vendor/goa.design/goa/v3/codegen/service/templates/server_interceptors.go.tpl @@ -0,0 +1,12 @@ +// ServerInterceptors defines the interface for all server-side interceptors. +// Server interceptors execute after the request is decoded and before the +// payload is sent to the service. The implementation is responsible for calling +// next to complete the request. +type ServerInterceptors interface { +{{- range .ServerInterceptors }} + {{- if .Description }} + {{ comment .Description }} + {{- end }} + {{ .Name }}(ctx context.Context, info *{{ .Name }}Info, next goa.Endpoint) (any, error) +{{- end }} +} diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/service.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/service.go.tpl index 5164c62016..6a3334a5bd 100644 --- a/vendor/goa.design/goa/v3/codegen/service/templates/service.go.tpl +++ b/vendor/goa.design/goa/v3/codegen/service/templates/service.go.tpl @@ -64,10 +64,14 @@ type {{ .Stream.Interface }} interface { {{- if .Stream.SendTypeRef }} {{ comment .Stream.SendDesc }} {{ .Stream.SendName }}({{ .Stream.SendTypeRef }}) error + {{ comment .Stream.SendWithContextDesc }} + {{ .Stream.SendWithContextName }}(context.Context, {{ .Stream.SendTypeRef }}) error {{- end }} {{- if .Stream.RecvTypeRef }} {{ comment .Stream.RecvDesc }} {{ .Stream.RecvName }}() ({{ .Stream.RecvTypeRef }}, error) + {{ comment .Stream.RecvWithContextDesc }} + {{ .Stream.RecvWithContextName }}(context.Context) ({{ .Stream.RecvTypeRef }}, error) {{- end }} {{- if .Stream.MustClose }} {{ comment "Close closes the stream." }} diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/service_client_init.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/service_client_init.go.tpl index 3f2302c524..20621066a3 100644 --- a/vendor/goa.design/goa/v3/codegen/service/templates/service_client_init.go.tpl +++ b/vendor/goa.design/goa/v3/codegen/service/templates/service_client_init.go.tpl @@ -1,8 +1,8 @@ {{ printf "New%s initializes a %q service client given the endpoints." .ClientVarName .Name | comment }} -func New{{ .ClientVarName }}({{ .ClientInitArgs }} goa.Endpoint) *{{ .ClientVarName }} { - return &{{ .ClientVarName }}{ -{{- range .Methods }} - {{ .VarName }}Endpoint: {{ .ArgName }}, -{{- end }} - } +func New{{ .ClientVarName }}({{ .ClientInitArgs }} goa.Endpoint{{ if .HasClientInterceptors }}, ci ClientInterceptors{{ end }}) *{{ .ClientVarName }} { + return &{{ .ClientVarName }}{ + {{- range .Methods }} + {{ .VarName }}Endpoint: {{ if .ClientInterceptors }}Wrap{{ .VarName }}ClientEndpoint({{ end }}{{ .ArgName }}{{ if .ClientInterceptors }}, ci){{ end }}, + {{- end }} + } } diff --git a/vendor/goa.design/goa/v3/codegen/service/templates/service_endpoints_init.go.tpl b/vendor/goa.design/goa/v3/codegen/service/templates/service_endpoints_init.go.tpl index 64a9803a6b..3f46fc4d88 100644 --- a/vendor/goa.design/goa/v3/codegen/service/templates/service_endpoints_init.go.tpl +++ b/vendor/goa.design/goa/v3/codegen/service/templates/service_endpoints_init.go.tpl @@ -1,14 +1,25 @@ - {{ printf "New%s wraps the methods of the %q service with endpoints." .VarName .Name | comment }} -func New{{ .VarName }}(s {{ .ServiceVarName }}) *{{ .VarName }} { +func New{{ .VarName }}(s {{ .ServiceVarName }}{{ if .HasServerInterceptors }}, si ServerInterceptors{{ end }}) *{{ .VarName }} { {{- if .Schemes }} // Casting service to Auther interface a := s.(Auther) {{- end }} +{{- if .HasServerInterceptors }} + endpoints := &{{ .VarName }}{ +{{- else }} return &{{ .VarName }}{ +{{- end }} {{- range .Methods }} {{ .VarName }}: New{{ .VarName }}Endpoint(s{{ range .Schemes }}, a.{{ .Type }}Auth{{ end }}), {{- end }} } +{{- if .HasServerInterceptors }} + {{- range .Methods }} + {{- if .ServerInterceptors }} + endpoints.{{ .VarName }} = Wrap{{ .VarName }}Endpoint(endpoints.{{ .VarName }}, si) + {{- end }} + {{- end }} + return endpoints +{{- end }} } \ No newline at end of file diff --git a/vendor/goa.design/goa/v3/codegen/service/testing.go b/vendor/goa.design/goa/v3/codegen/service/testing.go new file mode 100644 index 0000000000..28243ecfac --- /dev/null +++ b/vendor/goa.design/goa/v3/codegen/service/testing.go @@ -0,0 +1,42 @@ +package service + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "goa.design/goa/v3/eval" + "goa.design/goa/v3/expr" +) + +// initDSL initializes the DSL environment and returns the root. +func initDSL(t *testing.T) *expr.RootExpr { + // reset all roots and codegen data structures + Services = make(ServicesData) + eval.Reset() + expr.Root = new(expr.RootExpr) + expr.GeneratedResultTypes = new(expr.ResultTypesRoot) + expr.Root.API = expr.NewAPIExpr("test api", func() {}) + expr.Root.API.Servers = []*expr.ServerExpr{expr.Root.API.DefaultServer()} + root := expr.Root + require.NoError(t, eval.Register(root)) + require.NoError(t, eval.Register(expr.GeneratedResultTypes)) + return root +} + +// runDSL returns the DSL root resulting from running the given DSL. +func runDSL(t *testing.T, dsl func()) *expr.RootExpr { + root := initDSL(t) + require.True(t, eval.Execute(dsl, nil)) + require.NoError(t, eval.RunDSL()) + return root +} + +// runDSLWithError returns the DSL root and error from running the given DSL. +func runDSLWithError(t *testing.T, dsl func()) (*expr.RootExpr, error) { + root := initDSL(t) + require.True(t, eval.Execute(dsl, nil)) + err := eval.RunDSL() + require.Error(t, err) + return root, err +} diff --git a/vendor/goa.design/goa/v3/codegen/transformer.go b/vendor/goa.design/goa/v3/codegen/transformer.go index f4e0ba8787..f57c5810ef 100644 --- a/vendor/goa.design/goa/v3/codegen/transformer.go +++ b/vendor/goa.design/goa/v3/codegen/transformer.go @@ -242,6 +242,14 @@ func (a *AttributeScope) Name(att *expr.AttributeExpr, pkg string, ptr, useDefau // GoTransform algorithm does not allow for an override. return a.scope.GoTypeDef(att, ptr, useDefault) } + if n, ok := att.Meta["struct:type:name"]; ok { + // If the attribute has a "struct:type:name" meta then use it as the + // type name. + if pkg == "" { + return n[0] + } + return pkg + "." + n[0] + } return a.scope.GoFullTypeName(att, pkg) } diff --git a/vendor/goa.design/goa/v3/dsl/api.go b/vendor/goa.design/goa/v3/dsl/api.go index e34a4326b5..1cc7b9afe2 100644 --- a/vendor/goa.design/goa/v3/dsl/api.go +++ b/vendor/goa.design/goa/v3/dsl/api.go @@ -56,7 +56,7 @@ func API(name string, fn func()) *expr.APIExpr { // Title sets the API title. It is used by the generated OpenAPI specification. // -// Title must appear in a API expression. +// Title must appear in an API expression. // // Title accepts a single string argument. // @@ -75,7 +75,7 @@ func Title(val string) { // Version specifies the API version. One design describes one version. // -// Version must appear in a API expression. +// Version must appear in an API expression. // // Version accepts a single string argument. // @@ -94,7 +94,7 @@ func Version(ver string) { // Contact sets the API contact information. // -// Contact must appear in a API expression. +// Contact must appear in an API expression. // // Contact takes a single argument which is the defining DSL. // @@ -121,7 +121,7 @@ func Contact(fn func()) { // License sets the API license information. // -// License must appear in a API expression. +// License must appear in an API expression. // // License takes a single argument which is the defining DSL. // @@ -147,7 +147,7 @@ func License(fn func()) { // Randomizer sets the API example randomizer. // -// Randomizer must appear in a API expression. +// Randomizer must appear in an API expression. // // Randomizer takes a single argument which is an implementation of // expr.Randomizer. @@ -215,7 +215,7 @@ func Docs(fn func()) { // TermsOfService describes the API terms of services or links to them. // -// TermsOfService must appear in a API expression. +// TermsOfService must appear in an API expression. // // TermsOfService takes a single argument which is the TOS text or URL. // diff --git a/vendor/goa.design/goa/v3/dsl/attribute.go b/vendor/goa.design/goa/v3/dsl/attribute.go index 75f7408701..ba4adce7ae 100644 --- a/vendor/goa.design/goa/v3/dsl/attribute.go +++ b/vendor/goa.design/goa/v3/dsl/attribute.go @@ -229,13 +229,13 @@ func OneOf(name string, args ...any) { } fn, ok := args[len(args)-1].(func()) if !ok { - eval.ReportError("OneOf: last argument must be a function") + eval.InvalidArgError("function", args[len(args)-1]) } var desc string if len(args) > 1 { desc, ok = args[0].(string) if !ok { - eval.ReportError("OneOf: description must be a string") + eval.InvalidArgError("string", args[0]) } } Attribute(name, &expr.Union{TypeName: name}, desc, fn) diff --git a/vendor/goa.design/goa/v3/dsl/description.go b/vendor/goa.design/goa/v3/dsl/description.go index 931c4f2ab3..b8e9c78479 100644 --- a/vendor/goa.design/goa/v3/dsl/description.go +++ b/vendor/goa.design/goa/v3/dsl/description.go @@ -45,6 +45,8 @@ func Description(d string) { e.Description = d case *expr.GRPCResponseExpr: e.Description = d + case *expr.InterceptorExpr: + e.Description = d default: eval.IncompatibleDSL() } diff --git a/vendor/goa.design/goa/v3/dsl/http.go b/vendor/goa.design/goa/v3/dsl/http.go index e99cf08cf7..826d6f5335 100644 --- a/vendor/goa.design/goa/v3/dsl/http.go +++ b/vendor/goa.design/goa/v3/dsl/http.go @@ -233,7 +233,7 @@ func Produces(args ...string) { // As a special case, if you want to generate a path with a trailing slash, you can use // GET("/./") to generate a path such as '/foo/'. // -// Path must appear in a API HTTP expression or a Service HTTP expression. +// Path must appear in an API HTTP expression or a Service HTTP expression. // // Path accepts one argument: the HTTP path prefix. func Path(val string) { @@ -755,7 +755,7 @@ func MapParams(args ...any) { if len(args) > 0 { mapName, ok = args[0].(string) if !ok { - eval.ReportError("argument must be a string") + eval.InvalidArgError("string", args[0]) } } e.MapQueryParams = &mapName @@ -1166,7 +1166,7 @@ func cookies(exp eval.Expression) *expr.MappedAttributeExpr { } // params returns the mapped attribute containing the path and query params for -// the given expression if it's either the root, a API server, a service or an +// the given expression if it's either the root, an API server, a service or an // endpoint - nil otherwise. func params(exp eval.Expression) *expr.MappedAttributeExpr { switch e := exp.(type) { diff --git a/vendor/goa.design/goa/v3/dsl/interceptor.go b/vendor/goa.design/goa/v3/dsl/interceptor.go new file mode 100644 index 0000000000..44de81370a --- /dev/null +++ b/vendor/goa.design/goa/v3/dsl/interceptor.go @@ -0,0 +1,389 @@ +package dsl + +import ( + "goa.design/goa/v3/eval" + "goa.design/goa/v3/expr" +) + +// Interceptor defines a request interceptor. Interceptors provide a type-safe way +// to read and write from and to the request and response. +// +// Interceptor must appear in an API, Service or Method expression. +// +// Interceptor accepts two arguments: the name of the interceptor and the +// defining DSL. +// +// Example: +// +// var Cache = Interceptor("Cache", func() { +// Description("Server-side interceptor which implements a transparent cache for the loaded records") +// +// ReadPayload(func() { +// Attribute("id") +// }) +// +// WriteResult(func() { +// Attribute("cachedAt") +// }) +// }) +func Interceptor(name string, fn ...func()) *expr.InterceptorExpr { + if len(fn) > 1 { + eval.ReportError("interceptor %q cannot have multiple definitions", name) + return nil + } + i := &expr.InterceptorExpr{Name: name} + if name == "" { + eval.ReportError("interceptor name cannot be empty") + return i + } + if len(fn) > 0 { + if !eval.Execute(fn[0], i) { + return i + } + } + for _, i := range expr.Root.Interceptors { + if i.Name == name { + eval.ReportError("interceptor %q already defined", name) + return i + } + } + expr.Root.Interceptors = append(expr.Root.Interceptors, i) + return i +} + +// ReadPayload defines the payload attributes read by the interceptor. +// +// ReadPayload must appear in an interceptor DSL. +// +// ReadPayload takes a function as argument which can use the Attribute DSL to +// define the attributes read by the interceptor. +// +// Example: +// +// ReadPayload(func() { +// Attribute("id") +// }) +// +// ReadPayload also accepts user defined types: +// +// // Interceptor can read any payload field +// ReadPayload(MethodPayload) +func ReadPayload(arg any) { + setInterceptorAttribute(arg, func(i *expr.InterceptorExpr, attr *expr.AttributeExpr) { + i.ReadPayload = attr + }) +} + +// WritePayload defines the payload attributes written by the interceptor. +// +// WritePayload must appear in an interceptor DSL. +// +// WritePayload takes a function as argument which can use the Attribute DSL to +// define the attributes written by the interceptor. +// +// Example: +// +// WritePayload(func() { +// Attribute("auth") +// }) +// +// WritePayload also accepts user defined types: +// +// // Interceptor can write any payload field +// WritePayload(MethodPayload) +func WritePayload(arg any) { + setInterceptorAttribute(arg, func(i *expr.InterceptorExpr, attr *expr.AttributeExpr) { + i.WritePayload = attr + }) +} + +// ReadResult defines the result attributes read by the interceptor. +// +// ReadResult must appear in an interceptor DSL. +// +// ReadResult takes a function as argument which can use the Attribute DSL to +// define the attributes read by the interceptor. +// +// Example: +// +// ReadResult(func() { +// Attribute("cachedAt") +// }) +// +// ReadResult also accepts user defined types: +// +// // Interceptor can read any result field +// ReadResult(MethodResult) +func ReadResult(arg any) { + setInterceptorAttribute(arg, func(i *expr.InterceptorExpr, attr *expr.AttributeExpr) { + i.ReadResult = attr + }) +} + +// WriteResult defines the result attributes written by the interceptor. +// +// WriteResult must appear in an interceptor DSL. +// +// WriteResult takes a function as argument which can use the Attribute DSL to +// define the attributes written by the interceptor. +// +// Example: +// +// WriteResult(func() { +// Attribute("cachedAt") +// }) +// +// WriteResult also accepts user defined types: +// +// // Interceptor can write any result field +// WriteResult(MethodResult) +func WriteResult(arg any) { + setInterceptorAttribute(arg, func(i *expr.InterceptorExpr, attr *expr.AttributeExpr) { + i.WriteResult = attr + }) +} + +// ReadStreamingPayload defines the streaming payload attributes read by the interceptor. +// +// ReadStreamingPayload must appear in an interceptor DSL. +// +// ReadStreamingPayload takes a function as argument which can use the Attribute DSL to +// define the attributes read by the interceptor. +// +// Example: +// +// ReadStreamingPayload(func() { +// Attribute("id") +// }) +// +// ReadStreamingPayload also accepts user defined types: +// +// // Interceptor can read any streaming payload field +// ReadStreamingPayload(MethodStreamingPayload) +func ReadStreamingPayload(arg any) { + setInterceptorAttribute(arg, func(i *expr.InterceptorExpr, attr *expr.AttributeExpr) { + i.ReadStreamingPayload = attr + }) +} + +// WriteStreamingPayload defines the streaming payload attributes written by the interceptor. +// +// WriteStreamingPayload must appear in an interceptor DSL. +// +// WriteStreamingPayload takes a function as argument which can use the Attribute DSL to +// define the attributes written by the interceptor. +// +// Example: +// +// WriteStreamingPayload(func() { +// Attribute("id") +// }) +// +// WriteStreamingPayload also accepts user defined types: +// +// // Interceptor can write any streaming payload field +// WriteStreamingPayload(MethodStreamingPayload) +func WriteStreamingPayload(arg any) { + setInterceptorAttribute(arg, func(i *expr.InterceptorExpr, attr *expr.AttributeExpr) { + i.WriteStreamingPayload = attr + }) +} + +// ReadStreamingResult defines the streaming result attributes read by the interceptor. +// +// ReadStreamingResult must appear in an interceptor DSL. +// +// ReadStreamingResult takes a function as argument which can use the Attribute DSL to +// define the attributes read by the interceptor. +// +// Example: +// +// ReadStreamingResult(func() { +// Attribute("cachedAt") +// }) +// +// ReadStreamingResult also accepts user defined types: +// +// // Interceptor can read any streaming result field +// ReadStreamingResult(MethodStreamingResult) +func ReadStreamingResult(arg any) { + setInterceptorAttribute(arg, func(i *expr.InterceptorExpr, attr *expr.AttributeExpr) { + i.ReadStreamingResult = attr + }) +} + +// WriteStreamingResult defines the streaming result attributes written by the interceptor. +// +// WriteStreamingResult must appear in an interceptor DSL. +// +// WriteStreamingResult takes a function as argument which can use the Attribute DSL to +// define the attributes written by the interceptor. +// +// Example: +// +// WriteStreamingResult(func() { +// Attribute("cachedAt") +// }) +// +// WriteStreamingResult also accepts user defined types: +// +// // Interceptor can write any streaming result field +// WriteStreamingResult(MethodStreamingResult) +func WriteStreamingResult(arg any) { + setInterceptorAttribute(arg, func(i *expr.InterceptorExpr, attr *expr.AttributeExpr) { + i.WriteStreamingResult = attr + }) +} + +// ServerInterceptor lists the server-side interceptors that apply to all the +// API endpoints, all the service endpoints or a specific endpoint. +// +// ServerInterceptor must appear in an API, Service or Method expression. +// +// ServerInterceptor accepts one or more interceptor or interceptor names as +// arguments. ServerInterceptor can appear multiple times in the same DSL. +// +// Example: +// +// Method("get_record", func() { +// // Interceptor defined with the Interceptor DSL +// ServerInterceptor(SetDeadline) +// +// // Name of interceptor defined with the Interceptor DSL +// ServerInterceptor("Cache") +// +// // Interceptor defined inline +// ServerInterceptor(Interceptor("CheckUserID", func() { +// ReadPayload(func() { +// Attribute("auth") +// }) +// })) +// +// // ... rest of the method DSL +// }) +func ServerInterceptor(interceptors ...any) { + addInterceptors(interceptors, false) +} + +// ClientInterceptor lists the client-side interceptors that apply to all the +// API endpoints, all the service endpoints or a specific endpoint. +// +// ClientInterceptor must appear in an API, Service or Method expression. +// +// ClientInterceptor accepts one or more interceptor or interceptor names as +// arguments. ClientInterceptor can appear multiple times in the same DSL. +// +// Example: +// +// Method("get_record", func() { +// // Interceptor defined with the Interceptor DSL +// ClientInterceptor(Retry) +// +// // Name of interceptor defined with the Interceptor DSL +// ClientInterceptor("Cache") +// +// // Interceptor defined inline +// ClientInterceptor(Interceptor("Sign", func() { +// ReadPayload(func() { +// Attribute("user_id") +// }) +// WritePayload(func() { +// Attribute("auth") +// }) +// })) +// +// // ... rest of the method DSL +// }) +func ClientInterceptor(interceptors ...any) { + addInterceptors(interceptors, true) +} + +// setInterceptorAttribute is a helper function that handles the common logic for +// setting interceptor attributes (ReadPayload, WritePayload, ReadResult, WriteResult, ReadStreamingPayload, WriteStreamingPayload, ReadStreamingResult, WriteStreamingResult). +func setInterceptorAttribute(arg any, setter func(i *expr.InterceptorExpr, attr *expr.AttributeExpr)) { + i, ok := eval.Current().(*expr.InterceptorExpr) + if !ok { + eval.IncompatibleDSL() + return + } + + var attr *expr.AttributeExpr + switch fn := arg.(type) { + case func(): + attr = &expr.AttributeExpr{Type: &expr.Object{}} + if !eval.Execute(fn, attr) { + return + } + case *expr.AttributeExpr: + attr = fn + case expr.DataType: + attr = &expr.AttributeExpr{Type: fn} + default: + eval.InvalidArgError("type, attribute or func()", arg) + return + } + setter(i, attr) +} + +// addInterceptors is a helper function that validates and adds interceptors to +// the current expression. +func addInterceptors(interceptors []any, client bool) { + kind := "ServerInterceptor" + if client { + kind = "ClientInterceptor" + } + if len(interceptors) == 0 { + eval.ReportError("%s: at least one interceptor must be specified", kind) + return + } + + var ints []*expr.InterceptorExpr + for _, i := range interceptors { + switch i := i.(type) { + case *expr.InterceptorExpr: + ints = append(ints, i) + case string: + if i == "" { + eval.ReportError("%s: interceptor name cannot be empty", kind) + return + } + var found bool + for _, in := range expr.Root.Interceptors { + if in.Name == i { + ints = append(ints, in) + found = true + break + } + } + if !found { + eval.ReportError("%s: interceptor %q not found", kind, i) + } + default: + eval.ReportError("%s: invalid interceptor %v", kind, i) + } + } + + current := eval.Current() + switch actual := current.(type) { + case *expr.APIExpr: + if client { + actual.ClientInterceptors = append(actual.ClientInterceptors, ints...) + } else { + actual.ServerInterceptors = append(actual.ServerInterceptors, ints...) + } + case *expr.ServiceExpr: + if client { + actual.ClientInterceptors = append(actual.ClientInterceptors, ints...) + } else { + actual.ServerInterceptors = append(actual.ServerInterceptors, ints...) + } + case *expr.MethodExpr: + if client { + actual.ClientInterceptors = append(actual.ClientInterceptors, ints...) + } else { + actual.ServerInterceptors = append(actual.ServerInterceptors, ints...) + } + default: + eval.IncompatibleDSL() + } +} diff --git a/vendor/goa.design/goa/v3/dsl/meta.go b/vendor/goa.design/goa/v3/dsl/meta.go index 05f917f851..dc575c8003 100644 --- a/vendor/goa.design/goa/v3/dsl/meta.go +++ b/vendor/goa.design/goa/v3/dsl/meta.go @@ -5,6 +5,12 @@ import ( "goa.design/goa/v3/expr" ) +// DefaultProtoc is the default command to be invoked for generating code from protobuf schemas. +// You may use this to prepend arguments/flags to the command or revert to the default command. +// +// See also [Meta]; this is useful with the "protoc:cmd" key. +const DefaultProtoc = expr.DefaultProtoc + // Meta defines a set of key/value pairs that can be assigned to an object. Each // value consists of a slice of strings so that multiple invocation of the Meta // function on the same target using the same key builds up the slice. @@ -124,6 +130,32 @@ import ( // }) // }) // +// - "protoc:cmd" provides an alternate command to execute for protoc with +// optional arguments. Applicable to API and service definitions only. If used +// on an API definition the include paths are used for all services, unless +// specified otherwise for specific services. The first value will be used as +// the command, and the following values will be used as initial arguments to +// that command. The given command will have additional arguments appended and +// is expected to behave similar to protoc. +// +// Can be used to specify custom options or alternate implementations. The +// default command can be specified using DefaultProtoc. +// +// // Use Go run to run a drop-in replacement for protoc. +// var _ = API("myapi", func() { +// Meta("protoc:cmd", "go", "run", "github.com/duckbrain/goprotoc") +// }) +// +// // Specify the full path to protoc and turn on fatal warnings. +// var _ = Service("service1", func() { +// Meta("protoc:cmd", "/usr/bin/protoc", "--fatal_warnings") +// }) +// +// // Restore defaults for a specific service. +// var _ = Service("service2", func() { +// Meta("protoc:cmd", DefaultProtoc) +// }) +// // - "protoc:include" provides the list of import paths used to invoke protoc. // Applicable to API and service definitions only. If used on an API definition // the include paths are used for all services. @@ -240,6 +272,25 @@ import ( // Meta("openapi:extension:x-api", `{"foo":"bar"}`) // }) // +// - "openapi:additionalProperties" sets the OpenAPI additionalProperties field. +// The value can be true or false. Defaults to true. Applicable to types (including +// embedded Payload and Result definitions). +// +// var Foo = Type("Foo", func() { +// Attribute("name", String) +// Meta("openapi:additionalProperties", "false") +// }) +// +// Payload(Bar, func() { +// Attribute("name", String) +// Meta("openapi:additionalProperties", "false") +// }) +// +// Result(func() { +// Attribute("name", String) +// Meta("openapi:additionalProperties", "false") +// }) +// // - "openapi:typename" overrides the name of the type generated in the OpenAPI specification. // Applicable to types (including embedded Payload and Result definitions). // @@ -288,3 +339,42 @@ func Meta(name string, value ...string) { eval.IncompatibleDSL() } } + +// RemoveMeta removes a meta key from an object. +// +// RemoveMeta may appear where Meta can appear. +// +// RemoveMeta takes a single argument, the name of the meta key to remove. +func RemoveMeta(name string) { + switch e := eval.Current().(type) { + case *expr.APIExpr: + delete(e.Meta, name) + case *expr.ServerExpr: + delete(e.Meta, name) + case *expr.HostExpr: + delete(e.Meta, name) + case *expr.AttributeExpr: + delete(e.Meta, name) + case *expr.ResultTypeExpr: + delete(e.Meta, name) + case *expr.MethodExpr: + delete(e.Meta, name) + case *expr.ServiceExpr: + delete(e.Meta, name) + case *expr.HTTPServiceExpr: + delete(e.Meta, name) + case *expr.HTTPEndpointExpr: + delete(e.Meta, name) + case *expr.RouteExpr: + delete(e.Meta, name) + case *expr.HTTPFileServerExpr: + delete(e.Meta, name) + case *expr.HTTPResponseExpr: + delete(e.Meta, name) + case expr.CompositeExpr: + att := e.Attribute() + delete(att.Meta, name) + default: + eval.IncompatibleDSL() + } +} diff --git a/vendor/goa.design/goa/v3/dsl/result_type.go b/vendor/goa.design/goa/v3/dsl/result_type.go index d8e503b9e1..3bafe7c769 100644 --- a/vendor/goa.design/goa/v3/dsl/result_type.go +++ b/vendor/goa.design/goa/v3/dsl/result_type.go @@ -451,7 +451,7 @@ func Reference(t expr.DataType) { // }) // }) // -// var UpdateBottlePayload = Type("UpatePayload", func() { +// var UpdateBottlePayload = Type("UpdatePayload", func() { // Attribute("id", String, "ID of bottle to update") // Extend(CreateBottlePayload) // Adds attributes "name" and "vintage" // }) diff --git a/vendor/goa.design/goa/v3/dsl/security.go b/vendor/goa.design/goa/v3/dsl/security.go index 76aab1d8cb..0af951b22e 100644 --- a/vendor/goa.design/goa/v3/dsl/security.go +++ b/vendor/goa.design/goa/v3/dsl/security.go @@ -186,7 +186,7 @@ func JWTSecurity(name string, fn ...func()) *expr.SchemeExpr { // in the same scope in which case the client may validate any one of the // requirements for the request to be authorized. // -// Security must appear in a API, Service or Method expression. +// Security must appear in an API, Service or Method expression. // // Security accepts an arbitrary number of security schemes as argument // specified by name or by reference and an optional DSL function as last diff --git a/vendor/goa.design/goa/v3/dsl/server.go b/vendor/goa.design/goa/v3/dsl/server.go index dfb861ef7b..f2ffc42e90 100644 --- a/vendor/goa.design/goa/v3/dsl/server.go +++ b/vendor/goa.design/goa/v3/dsl/server.go @@ -18,7 +18,7 @@ import ( // the first host is used to set the OpenAPI v2 specification 'host' and // 'basePath' values. // -// Server must appear in a API expression. +// Server must appear in an API expression. // // Server takes two arguments: the name of the server and the defining DSL. // diff --git a/vendor/goa.design/goa/v3/dsl/user_type.go b/vendor/goa.design/goa/v3/dsl/user_type.go index bdd67ecb96..0c7041be20 100644 --- a/vendor/goa.design/goa/v3/dsl/user_type.go +++ b/vendor/goa.design/goa/v3/dsl/user_type.go @@ -85,7 +85,7 @@ func Type(name string, args ...any) expr.UserType { if len(args) == 2 { d, ok := args[1].(func()) if !ok { - eval.ReportError("third argument must be a function") + eval.InvalidArgError("function", args[1]) return nil } fn = d diff --git a/vendor/goa.design/goa/v3/expr/api.go b/vendor/goa.design/goa/v3/expr/api.go index 01ed202620..f5e4557a5c 100644 --- a/vendor/goa.design/goa/v3/expr/api.go +++ b/vendor/goa.design/goa/v3/expr/api.go @@ -7,7 +7,7 @@ import ( ) type ( - // APIExpr contains the global properties for a API expression. + // APIExpr contains the global properties for an API expression. APIExpr struct { // DSLFunc contains the DSL used to initialize the expression. eval.DSLFunc @@ -36,6 +36,10 @@ type ( // potentially multiple schemes. Incoming requests must validate // at least one requirement to be authorized. Requirements []*SecurityExpr + // ClientInterceptors is the list of API client interceptors. + ClientInterceptors []*InterceptorExpr + // ServerInterceptors is the list of API server interceptors. + ServerInterceptors []*InterceptorExpr // HTTP contains the HTTP specific API level expressions. HTTP *HTTPExpr // GRPC contains the gRPC specific API level expressions. diff --git a/vendor/goa.design/goa/v3/expr/attribute.go b/vendor/goa.design/goa/v3/expr/attribute.go index c4a6f0e0c2..0742c85f3d 100644 --- a/vendor/goa.design/goa/v3/expr/attribute.go +++ b/vendor/goa.design/goa/v3/expr/attribute.go @@ -320,6 +320,12 @@ func (a *AttributeExpr) Finalize() { } a.Merge(ru.Attribute()) } + + // Now that we've merged the bases, we can clear them. This + // avoids issues where the bases are dupped and modifications + // made to the originals are not reflected in the dups. + a.Bases = nil + for _, nat := range *AsObject(a.Type) { if pkgPath != "" { if u := AsUnion(nat.Attribute.Type); u != nil { diff --git a/vendor/goa.design/goa/v3/expr/http_body_types.go b/vendor/goa.design/goa/v3/expr/http_body_types.go index 09724a19e9..bd44b5b2a2 100644 --- a/vendor/goa.design/goa/v3/expr/http_body_types.go +++ b/vendor/goa.design/goa/v3/expr/http_body_types.go @@ -192,11 +192,16 @@ func httpRequestBody(a *HTTPEndpointExpr) *AttributeExpr { } appendSuffix(ut.Attribute().Type, suffix) - // Remember openapi typename for example to generate friendly OpenAPI specs. if t, ok := payload.Type.(UserType); ok { + // Remember openapi typename for example to generate friendly OpenAPI specs. if m, ok := t.Attribute().Meta["openapi:typename"]; ok { ut.AttributeExpr.AddMeta("openapi:typename", m...) } + + // Remember additionalProperties. + if m, ok := t.Attribute().Meta["openapi:additionalProperties"]; ok { + ut.AttributeExpr.AddMeta("openapi:additionalProperties", m...) + } } return &AttributeExpr{ @@ -334,13 +339,18 @@ func buildHTTPResponseBody(name string, attr *AttributeExpr, resp *HTTPResponseE UID: concat(svc.Name(), "#", name), } - // Remember original type name and openapi typename for example - // to generate friendly OpenAPI specs. if t, ok := attr.Type.(UserType); ok { + // Remember original type name and openapi typename for example + // to generate friendly OpenAPI specs. userType.AttributeExpr.AddMeta("name:original", t.Name()) if m, ok := t.Attribute().Meta["openapi:typename"]; ok { userType.AttributeExpr.AddMeta("openapi:typename", m...) } + + // Remember additionalProperties. + if m, ok := t.Attribute().Meta["openapi:additionalProperties"]; ok { + userType.AttributeExpr.AddMeta("openapi:additionalProperties", m...) + } } appendSuffix(userType.Attribute().Type, suffix) diff --git a/vendor/goa.design/goa/v3/expr/http_endpoint.go b/vendor/goa.design/goa/v3/expr/http_endpoint.go index 774a3a9f78..bc6c92a679 100644 --- a/vendor/goa.design/goa/v3/expr/http_endpoint.go +++ b/vendor/goa.design/goa/v3/expr/http_endpoint.go @@ -740,7 +740,7 @@ func (e *HTTPEndpointExpr) validateParams() *eval.ValidationErrors { // We have to figure out the actual type for the params because the actual // type is initialized only during the finalize phase. In the validation // phase, all param types are string type by default unless specified - // expliclty. + // explicitly. initAttr(pparams, e.MethodExpr.Payload) initAttr(qparams, e.MethodExpr.Payload) @@ -878,7 +878,7 @@ func (e *HTTPEndpointExpr) validateHeadersAndCookies() *eval.ValidationErrors { // EvalName returns the generic definition name used in error messages. func (r *RouteExpr) EvalName() string { - return fmt.Sprintf(`route %s "%s" of %s`, r.Method, r.Path, r.Endpoint.EvalName()) + return fmt.Sprintf(`route %s %q of %s`, r.Method, r.Path, r.Endpoint.EvalName()) } // Validate validates a route expression by ensuring that the route parameters diff --git a/vendor/goa.design/goa/v3/expr/interceptor.go b/vendor/goa.design/goa/v3/expr/interceptor.go new file mode 100644 index 0000000000..31a243351b --- /dev/null +++ b/vendor/goa.design/goa/v3/expr/interceptor.go @@ -0,0 +1,124 @@ +package expr + +import ( + "goa.design/goa/v3/eval" +) + +type ( + // InterceptorExpr describes an interceptor definition in the design. + // Interceptors are used to inject user code into the request/response processing pipeline. + // There are four kinds of interceptors, in order of execution: + // * client-side payload: executes after the payload is encoded and before the request is sent to the server + // * server-side request: executes after the request is decoded and before the payload is sent to the service + // * server-side result: executes after the service returns a result and before the response is encoded + // * client-side response: executes after the response is decoded and before the result is sent to the client + InterceptorExpr struct { + // Name is the name of the interceptor + Name string + // Description is the optional description of the interceptor + Description string + // ReadPayload lists the payload attribute names read by the interceptor + ReadPayload *AttributeExpr + // WritePayload lists the payload attribute names written by the interceptor + WritePayload *AttributeExpr + // ReadResult lists the result attribute names read by the interceptor + ReadResult *AttributeExpr + // WriteResult lists the result attribute names written by the interceptor + WriteResult *AttributeExpr + // ReadStreamingPayload lists the streaming payload attribute names read by the interceptor + ReadStreamingPayload *AttributeExpr + // WriteStreamingPayload lists the streaming payload attribute names written by the interceptor + WriteStreamingPayload *AttributeExpr + // ReadStreamingResult lists the streaming result attribute names read by the interceptor + ReadStreamingResult *AttributeExpr + // WriteStreamingResult lists the streaming result attribute names written by the interceptor + WriteStreamingResult *AttributeExpr + } +) + +// EvalName returns the generic expression name used in error messages. +func (i *InterceptorExpr) EvalName() string { + return "interceptor " + i.Name +} + +// validate validates the interceptor. +func (i *InterceptorExpr) validate(m *MethodExpr) *eval.ValidationErrors { + verr := new(eval.ValidationErrors) + + if i.ReadPayload != nil || i.WritePayload != nil { + payloadObj := AsObject(m.Payload.Type) + if payloadObj == nil { + verr.Add(m, "interceptor %q cannot be applied because the method payload is not an object", i.Name) + } + if i.ReadPayload != nil { + i.validateAttributeAccess(m, "read payload", verr, payloadObj, i.ReadPayload) + } + if i.WritePayload != nil { + i.validateAttributeAccess(m, "write payload", verr, payloadObj, i.WritePayload) + } + } + + if i.ReadResult != nil || i.WriteResult != nil { + if m.IsResultStreaming() { + verr.Add(m, "interceptor %q cannot be applied because the method result is streaming", i.Name) + } + resultObj := AsObject(m.Result.Type) + if resultObj == nil { + verr.Add(m, "interceptor %q cannot be applied because the method result is not an object", i.Name) + } + if i.ReadResult != nil { + i.validateAttributeAccess(m, "read result", verr, resultObj, i.ReadResult) + } + if i.WriteResult != nil { + i.validateAttributeAccess(m, "write result", verr, resultObj, i.WriteResult) + } + } + + if i.ReadStreamingPayload != nil || i.WriteStreamingPayload != nil { + if !m.IsPayloadStreaming() { + verr.Add(m, "interceptor %q cannot be applied because the method payload is not streaming", i.Name) + } + payloadObj := AsObject(m.StreamingPayload.Type) + if payloadObj == nil { + verr.Add(m, "interceptor %q cannot be applied because the method payload is not an object", i.Name) + } + if i.ReadStreamingPayload != nil { + i.validateAttributeAccess(m, "read streaming payload", verr, payloadObj, i.ReadStreamingPayload) + } + if i.WriteStreamingPayload != nil { + i.validateAttributeAccess(m, "write streaming payload", verr, payloadObj, i.WriteStreamingPayload) + } + } + + if i.ReadStreamingResult != nil || i.WriteStreamingResult != nil { + if !m.IsResultStreaming() { + verr.Add(m, "interceptor %q cannot be applied because the method result is not streaming", i.Name) + } + resultObj := AsObject(m.Result.Type) + if resultObj == nil { + verr.Add(m, "interceptor %q cannot be applied because the method result is not an object", i.Name) + } + if i.ReadStreamingResult != nil { + i.validateAttributeAccess(m, "read streaming result", verr, resultObj, i.ReadStreamingResult) + } + if i.WriteStreamingResult != nil { + i.validateAttributeAccess(m, "write streaming result", verr, resultObj, i.WriteStreamingResult) + } + } + + return verr +} + +// validateAttributeAccess validates that all attributes in attr exist in obj +func (i *InterceptorExpr) validateAttributeAccess(m *MethodExpr, source string, verr *eval.ValidationErrors, obj *Object, attr *AttributeExpr) { + attrObj := AsObject(attr.Type) + if attrObj == nil { + verr.Add(m, "interceptor %q %s attribute is not an object", i.Name, source) + return + } + for _, att := range *attrObj { + if obj.Attribute(att.Name) == nil { + verr.Add(m, "interceptor %q cannot %s attribute %q: attribute does not exist", i.Name, source, att.Name) + } + } +} diff --git a/vendor/goa.design/goa/v3/expr/method.go b/vendor/goa.design/goa/v3/expr/method.go index 3ba80728bd..0183545e0e 100644 --- a/vendor/goa.design/goa/v3/expr/method.go +++ b/vendor/goa.design/goa/v3/expr/method.go @@ -32,6 +32,10 @@ type ( // schemes. Incoming requests must validate at least one // requirement to be authorized. Requirements []*SecurityExpr + // ClientInterceptors is the list of client interceptors. + ClientInterceptors []*InterceptorExpr + // ServerInterceptors is the list of server interceptors. + ServerInterceptors []*InterceptorExpr // Service that owns method. Service *ServiceExpr // Meta is an arbitrary set of key/value pairs, see dsl.Meta @@ -84,7 +88,8 @@ func (m *MethodExpr) EvalName() string { } // Prepare makes sure the payload and result types are initialized (to the Empty -// type if nil). +// type if nil) and merges the method interceptors with the API and service level +// interceptors. func (m *MethodExpr) Prepare() { if m.Payload == nil { m.Payload = &AttributeExpr{Type: Empty} @@ -97,11 +102,22 @@ func (m *MethodExpr) Prepare() { } } -// Validate validates the method payloads, results, and errors (if any). +// Validate validates the method payloads, results, errors, security +// requirements, and interceptors. func (m *MethodExpr) Validate() error { verr := new(eval.ValidationErrors) verr.Merge(m.Payload.Validate("payload", m)) - // validate security scheme requirements + verr.Merge(m.StreamingPayload.Validate("streaming_payload", m)) + verr.Merge(m.Result.Validate("result", m)) + verr.Merge(m.validateRequirements()) + verr.Merge(m.validateErrors()) + verr.Merge(m.validateInterceptors()) + return verr +} + +// validateRequirements validates the security requirements. +func (m *MethodExpr) validateRequirements() *eval.ValidationErrors { + verr := new(eval.ValidationErrors) var requirements []*SecurityExpr if len(m.Requirements) > 0 { requirements = m.Requirements @@ -185,12 +201,12 @@ func (m *MethodExpr) Validate() error { verr.Add(m, "payload of method %q of service %q defines a OAuth2 access token attribute, but no OAuth2 security scheme exist", m.Name, m.Service.Name) } } - if m.StreamingPayload.Type != Empty { - verr.Merge(m.StreamingPayload.Validate("streaming_payload", m)) - } - if m.Result.Type != Empty { - verr.Merge(m.Result.Validate("result", m)) - } + return verr +} + +// validateErrors validates the method errors. +func (m *MethodExpr) validateErrors() *eval.ValidationErrors { + verr := new(eval.ValidationErrors) for i, e := range m.Errors { if err := e.Validate(); err != nil { var verrs *eval.ValidationErrors @@ -220,6 +236,44 @@ func (m *MethodExpr) Validate() error { return verr } +// validateInterceptors validates the method interceptors. +func (m *MethodExpr) validateInterceptors() *eval.ValidationErrors { + verr := new(eval.ValidationErrors) + m.ClientInterceptors = mergeInterceptors(m.ClientInterceptors, m.Service.ClientInterceptors, Root.API.ClientInterceptors) + for _, i := range m.ClientInterceptors { + verr.Merge(i.validate(m)) + } + m.ServerInterceptors = mergeInterceptors(m.ServerInterceptors, m.Service.ServerInterceptors, Root.API.ServerInterceptors) + for _, i := range m.ServerInterceptors { + verr.Merge(i.validate(m)) + } + return verr +} + +// mergeInterceptors merges interceptors from different levels (method, service, API) +// while avoiding duplicates. The order of precedence is: method > service > API. +func mergeInterceptors(methodLevel, serviceLevel, apiLevel []*InterceptorExpr) []*InterceptorExpr { + existing := make(map[string]struct{}) + result := make([]*InterceptorExpr, 0, len(methodLevel)+len(serviceLevel)+len(apiLevel)) + + for _, i := range methodLevel { + existing[i.Name] = struct{}{} + result = append(result, i) + } + for _, i := range serviceLevel { + if _, ok := existing[i.Name]; !ok { + result = append(result, i) + existing[i.Name] = struct{}{} + } + } + for _, i := range apiLevel { + if _, ok := existing[i.Name]; !ok { + result = append(result, i) + } + } + return result +} + // hasTag is a helper function that traverses the given attribute and all its // bases recursively looking for an attribute with the given tag meta. This // recursion is only needed for attributes that have not been finalized yet. diff --git a/vendor/goa.design/goa/v3/expr/root.go b/vendor/goa.design/goa/v3/expr/root.go index 0240e54e1f..94b34d8861 100644 --- a/vendor/goa.design/goa/v3/expr/root.go +++ b/vendor/goa.design/goa/v3/expr/root.go @@ -11,6 +11,9 @@ import ( // Root is the root object built by the DSL. var Root = new(RootExpr) +// DefaultProtoc is the default command to be invoked for generating code from protobuf schemas. +const DefaultProtoc = "protoc" + type ( // RootExpr is the struct built by the DSL on process start. RootExpr struct { @@ -18,6 +21,8 @@ type ( API *APIExpr // Services contains the list of services exposed by the API. Services []*ServiceExpr + // Interceptors contains the list of interceptors. + Interceptors []*InterceptorExpr // Errors contains the list of errors returned by all the API // methods. Errors []*ErrorExpr diff --git a/vendor/goa.design/goa/v3/expr/service.go b/vendor/goa.design/goa/v3/expr/service.go index 1a7d88e9cf..ab906c4688 100644 --- a/vendor/goa.design/goa/v3/expr/service.go +++ b/vendor/goa.design/goa/v3/expr/service.go @@ -27,6 +27,10 @@ type ( // potentially multiple schemes. Incoming requests must validate // at least one requirement to be authorized. Requirements []*SecurityExpr + // ClientInterceptors is the list of client interceptors. + ClientInterceptors []*InterceptorExpr + // ServerInterceptors is the list of server interceptors. + ServerInterceptors []*InterceptorExpr // Meta is a set of key/value pairs with semantic that is // specific to each generator. Meta MetaExpr diff --git a/vendor/goa.design/goa/v3/grpc/codegen/client-no-server-pkgpath.golden b/vendor/goa.design/goa/v3/grpc/codegen/client-no-server-pkgpath.golden deleted file mode 100644 index 56ca0253c8..0000000000 --- a/vendor/goa.design/goa/v3/grpc/codegen/client-no-server-pkgpath.golden +++ /dev/null @@ -1,17 +0,0 @@ -import ( - "fmt" - cli "my/pkg/path/grpc/cli/test_api" - "os" - - goa "goa.design/goa/v3/pkg" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" -) - -func doGRPC(_, host string, _ int, _ bool) (goa.Endpoint, any, error) { - conn, err := grpc.NewClient(host, grpc.WithTransportCredentials(insecure.NewCredentials())) - if err != nil { - fmt.Fprintf(os.Stderr, "could not connect to gRPC server at %s: %v\n", host, err) - } - return cli.ParseEndpoint(conn) -} diff --git a/vendor/goa.design/goa/v3/grpc/codegen/client-no-server.golden b/vendor/goa.design/goa/v3/grpc/codegen/client-no-server.golden deleted file mode 100644 index b6a7c341da..0000000000 --- a/vendor/goa.design/goa/v3/grpc/codegen/client-no-server.golden +++ /dev/null @@ -1,17 +0,0 @@ -import ( - "fmt" - cli "grpc/cli/test_api" - "os" - - goa "goa.design/goa/v3/pkg" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" -) - -func doGRPC(_, host string, _ int, _ bool) (goa.Endpoint, any, error) { - conn, err := grpc.NewClient(host, grpc.WithTransportCredentials(insecure.NewCredentials())) - if err != nil { - fmt.Fprintf(os.Stderr, "could not connect to gRPC server at %s: %v\n", host, err) - } - return cli.ParseEndpoint(conn) -} diff --git a/vendor/goa.design/goa/v3/grpc/codegen/client-server-hosting-multiple-services-pkgpath.golden b/vendor/goa.design/goa/v3/grpc/codegen/client-server-hosting-multiple-services-pkgpath.golden deleted file mode 100644 index 22ea9249b5..0000000000 --- a/vendor/goa.design/goa/v3/grpc/codegen/client-server-hosting-multiple-services-pkgpath.golden +++ /dev/null @@ -1,17 +0,0 @@ -import ( - "fmt" - cli "my/pkg/path/grpc/cli/single_host" - "os" - - goa "goa.design/goa/v3/pkg" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" -) - -func doGRPC(_, host string, _ int, _ bool) (goa.Endpoint, any, error) { - conn, err := grpc.NewClient(host, grpc.WithTransportCredentials(insecure.NewCredentials())) - if err != nil { - fmt.Fprintf(os.Stderr, "could not connect to gRPC server at %s: %v\n", host, err) - } - return cli.ParseEndpoint(conn) -} diff --git a/vendor/goa.design/goa/v3/grpc/codegen/client-server-hosting-multiple-services.golden b/vendor/goa.design/goa/v3/grpc/codegen/client-server-hosting-multiple-services.golden deleted file mode 100644 index 6956659be3..0000000000 --- a/vendor/goa.design/goa/v3/grpc/codegen/client-server-hosting-multiple-services.golden +++ /dev/null @@ -1,17 +0,0 @@ -import ( - "fmt" - cli "grpc/cli/single_host" - "os" - - goa "goa.design/goa/v3/pkg" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" -) - -func doGRPC(_, host string, _ int, _ bool) (goa.Endpoint, any, error) { - conn, err := grpc.NewClient(host, grpc.WithTransportCredentials(insecure.NewCredentials())) - if err != nil { - fmt.Fprintf(os.Stderr, "could not connect to gRPC server at %s: %v\n", host, err) - } - return cli.ParseEndpoint(conn) -} diff --git a/vendor/goa.design/goa/v3/grpc/codegen/client-server-hosting-service-subset-pkgpath.golden b/vendor/goa.design/goa/v3/grpc/codegen/client-server-hosting-service-subset-pkgpath.golden deleted file mode 100644 index 22ea9249b5..0000000000 --- a/vendor/goa.design/goa/v3/grpc/codegen/client-server-hosting-service-subset-pkgpath.golden +++ /dev/null @@ -1,17 +0,0 @@ -import ( - "fmt" - cli "my/pkg/path/grpc/cli/single_host" - "os" - - goa "goa.design/goa/v3/pkg" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" -) - -func doGRPC(_, host string, _ int, _ bool) (goa.Endpoint, any, error) { - conn, err := grpc.NewClient(host, grpc.WithTransportCredentials(insecure.NewCredentials())) - if err != nil { - fmt.Fprintf(os.Stderr, "could not connect to gRPC server at %s: %v\n", host, err) - } - return cli.ParseEndpoint(conn) -} diff --git a/vendor/goa.design/goa/v3/grpc/codegen/client-server-hosting-service-subset.golden b/vendor/goa.design/goa/v3/grpc/codegen/client-server-hosting-service-subset.golden deleted file mode 100644 index 6956659be3..0000000000 --- a/vendor/goa.design/goa/v3/grpc/codegen/client-server-hosting-service-subset.golden +++ /dev/null @@ -1,17 +0,0 @@ -import ( - "fmt" - cli "grpc/cli/single_host" - "os" - - goa "goa.design/goa/v3/pkg" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" -) - -func doGRPC(_, host string, _ int, _ bool) (goa.Endpoint, any, error) { - conn, err := grpc.NewClient(host, grpc.WithTransportCredentials(insecure.NewCredentials())) - if err != nil { - fmt.Fprintf(os.Stderr, "could not connect to gRPC server at %s: %v\n", host, err) - } - return cli.ParseEndpoint(conn) -} diff --git a/vendor/goa.design/goa/v3/grpc/codegen/client.go b/vendor/goa.design/goa/v3/grpc/codegen/client.go index fd77174a32..f6669772f2 100644 --- a/vendor/goa.design/goa/v3/grpc/codegen/client.go +++ b/vendor/goa.design/goa/v3/grpc/codegen/client.go @@ -65,7 +65,7 @@ func client(genpkg string, svc *expr.GRPCServiceExpr) *codegen.File { } } sections = append(sections, &codegen.SectionTemplate{ - Name: "client-init", + Name: "grpc-client-init", Source: readTemplate("client_init"), Data: data, }) diff --git a/vendor/goa.design/goa/v3/grpc/codegen/client_cli.go b/vendor/goa.design/goa/v3/grpc/codegen/client_cli.go index 275828a953..4f6c2b8df2 100644 --- a/vendor/goa.design/goa/v3/grpc/codegen/client_cli.go +++ b/vendor/goa.design/goa/v3/grpc/codegen/client_cli.go @@ -19,31 +19,27 @@ func ClientCLIFiles(genpkg string, root *expr.RootExpr) []*codegen.File { data []*cli.CommandData svcs []*expr.GRPCServiceExpr ) - { - for _, svc := range root.API.GRPC.Services { - if len(svc.GRPCEndpoints) == 0 { - continue - } - sd := GRPCServices.Get(svc.Name()) - command := cli.BuildCommandData(sd.Service) - for _, e := range sd.Endpoints { - flags, buildFunction := buildFlags(e) - subcmd := cli.BuildSubcommandData(sd.Service.Name, e.Method, buildFunction, flags) - command.Subcommands = append(command.Subcommands, subcmd) - } - command.Example = command.Subcommands[0].Example - data = append(data, command) - svcs = append(svcs, svc) + for _, svc := range root.API.GRPC.Services { + if len(svc.GRPCEndpoints) == 0 { + continue } + sd := GRPCServices.Get(svc.Name()) + command := cli.BuildCommandData(sd.Service) + for _, e := range sd.Endpoints { + flags, buildFunction := buildFlags(e) + subcmd := cli.BuildSubcommandData(sd.Service, e.Method, buildFunction, flags) + command.Subcommands = append(command.Subcommands, subcmd) + } + command.Example = command.Subcommands[0].Example + data = append(data, command) + svcs = append(svcs, svc) } var files []*codegen.File - { - for _, svr := range root.API.Servers { - files = append(files, endpointParser(genpkg, root, svr, data)) - } - for i, svc := range svcs { - files = append(files, payloadBuilders(genpkg, svc, data[i])) - } + for _, svr := range root.API.Servers { + files = append(files, endpointParser(genpkg, root, svr, data)) + } + for i, svc := range svcs { + files = append(files, payloadBuilders(genpkg, svc, data[i])) } return files } @@ -71,15 +67,17 @@ func endpointParser(genpkg string, root *expr.RootExpr, svr *expr.ServerExpr, da continue } svcName := sd.Service.PathName - specs = append(specs, &codegen.ImportSpec{ - Path: path.Join(genpkg, "grpc", svcName, "client"), - Name: sd.Service.PkgName + "c", - }) - specs = append(specs, &codegen.ImportSpec{ - Path: path.Join(genpkg, "grpc", svcName, pbPkgName), - Name: svcName + pbPkgName, - }) + specs = append(specs, + &codegen.ImportSpec{Path: path.Join(genpkg, "grpc", svcName, "client"), Name: sd.Service.PkgName + "c"}, + &codegen.ImportSpec{Path: path.Join(genpkg, "grpc", svcName, pbPkgName), Name: svcName + pbPkgName}) specs = append(specs, sd.Service.UserTypeImports...) + // Add interceptors import if service has client interceptors + if len(sd.Service.ClientInterceptors) > 0 { + specs = append(specs, &codegen.ImportSpec{ + Path: genpkg + "/" + sd.Service.PathName, + Name: sd.Service.PkgName, + }) + } } sections := []*codegen.SectionTemplate{ @@ -87,7 +85,7 @@ func endpointParser(genpkg string, root *expr.RootExpr, svr *expr.ServerExpr, da cli.UsageCommands(data), cli.UsageExamples(data), { - Name: "parse-endpoint", + Name: "parse-endpoint-grpc", Source: readTemplate("parse_endpoint"), Data: struct { FlagsCode string diff --git a/vendor/goa.design/goa/v3/grpc/codegen/example_cli.go b/vendor/goa.design/goa/v3/grpc/codegen/example_cli.go index 36eee89f7b..8e346f5c2c 100644 --- a/vendor/goa.design/goa/v3/grpc/codegen/example_cli.go +++ b/vendor/goa.design/goa/v3/grpc/codegen/example_cli.go @@ -24,9 +24,10 @@ func ExampleCLIFiles(genpkg string, root *expr.RootExpr) []*codegen.File { // exampleCLI returns an example client tool HTTP implementation for the given // server expression. -func exampleCLI(genpkg string, root *expr.RootExpr, svr *expr.ServerExpr) *codegen.File { +func exampleCLI(genpkg string, _ *expr.RootExpr, svr *expr.ServerExpr) *codegen.File { var ( mainPath string + rootPath string svrdata = example.Servers.Get(svr) ) @@ -35,22 +36,11 @@ func exampleCLI(genpkg string, root *expr.RootExpr, svr *expr.ServerExpr) *codeg if _, err := os.Stat(mainPath); !os.IsNotExist(err) { return nil // file already exists, skip it. } - } - - var ( - rootPath string - apiPkg string - - scope = codegen.NewNameScope() - ) - { - // genpkg is created by path.Join so the separator is / regardless of operating system idx := strings.LastIndex(genpkg, string("/")) rootPath = "." if idx > 0 { rootPath = genpkg[:idx] } - apiPkg = scope.Unique(strings.ToLower(codegen.Goify(root.API.Name, false)), "api") } var ( @@ -68,11 +58,18 @@ func exampleCLI(genpkg string, root *expr.RootExpr, svr *expr.ServerExpr) *codeg {Path: "time"}, codegen.GoaImport(""), codegen.GoaNamedImport("grpc", "goagrpc"), - {Path: rootPath, Name: apiPkg}, + {Path: rootPath + "/interceptors"}, {Path: path.Join(genpkg, "grpc", "cli", svrdata.Dir), Name: "cli"}, } } + var svcData []*ServiceData + for _, svc := range svr.Services { + if data := GRPCServices.Get(svc); data != nil { + svcData = append(svcData, data) + } + } + var ( sections []*codegen.SectionTemplate ) @@ -82,7 +79,11 @@ func exampleCLI(genpkg string, root *expr.RootExpr, svr *expr.ServerExpr) *codeg { Name: "do-grpc-cli", Source: readTemplate("do_grpc_cli"), - Data: svrdata, + Data: map[string]any{ + "DefaultTransport": svrdata.DefaultTransport(), + "Services": svcData, + "InterceptorsPkg": "interceptors", + }, }, } } diff --git a/vendor/goa.design/goa/v3/grpc/codegen/proto.go b/vendor/goa.design/goa/v3/grpc/codegen/proto.go index 1a1f6bf883..09598be28a 100644 --- a/vendor/goa.design/goa/v3/grpc/codegen/proto.go +++ b/vendor/goa.design/goa/v3/grpc/codegen/proto.go @@ -83,7 +83,19 @@ func protoFile(genpkg string, svc *expr.GRPCServiceExpr) *codegen.File { runProtoc := func(path string) error { includes := svc.ServiceExpr.Meta["protoc:include"] includes = append(includes, expr.Root.API.Meta["protoc:include"]...) - return protoc(path, includes) + + cmd := defaultProtocCmd + if c, ok := expr.Root.API.Meta["protoc:cmd"]; ok { + cmd = c + } + if c, ok := svc.ServiceExpr.Meta["protoc:cmd"]; ok { + cmd = c + } + if len(cmd) == 0 { + return fmt.Errorf(`Meta("protoc:cmd"): must be given arguments`) + } + + return protoc(cmd, path, includes) } return &codegen.File{ @@ -100,7 +112,9 @@ func pkgName(svc *expr.GRPCServiceExpr, svcName string) string { return codegen.SnakeCase(svcName) } -func protoc(path string, includes []string) error { +var defaultProtocCmd = []string{expr.DefaultProtoc} + +func protoc(protocCmd []string, path string, includes []string) error { dir := filepath.Dir(path) if err := os.MkdirAll(dir, 0750); err != nil { return err @@ -117,7 +131,7 @@ func protoc(path string, includes []string) error { for _, include := range includes { args = append(args, "-I", include) } - cmd := exec.Command("protoc", args...) + cmd := exec.Command(protocCmd[0], append(protocCmd[1:len(protocCmd):len(protocCmd)], args...)...) cmd.Dir = filepath.Dir(path) if output, err := cmd.CombinedOutput(); err != nil { diff --git a/vendor/goa.design/goa/v3/grpc/codegen/service_data.go b/vendor/goa.design/goa/v3/grpc/codegen/service_data.go index dab2d28d15..442d8d0fd3 100644 --- a/vendor/goa.design/goa/v3/grpc/codegen/service_data.go +++ b/vendor/goa.design/goa/v3/grpc/codegen/service_data.go @@ -332,6 +332,10 @@ type ( SendName string // SendDesc is the description for the send function. SendDesc string + // SendWithContextName is the name of the send function with context. + SendWithContextName string + // SendWithContextDesc is the description for the send function with context. + SendWithContextDesc string // SendRef is the fully qualified reference to the type sent across the // stream. SendRef string @@ -347,6 +351,10 @@ type ( RecvName string // RecvDesc is the description for the recv function. RecvDesc string + // RecvWithContextName is the name of the receive function with context. + RecvWithContextName string + // RecvWithContextDesc is the description for the recv function with context. + RecvWithContextDesc string // RecvRef is the fully qualified reference to the type received from the // stream. RecvRef string @@ -393,7 +401,7 @@ func (d ServicesData) Get(name string) *ServiceData { return d[name] } -// Endpoint returns the endoint data for the endpoint with the given name, nil +// Endpoint returns the endpoint data for the endpoint with the given name, nil // if there isn't one. func (sd *ServiceData) Endpoint(name string) *EndpointData { for _, ed := range sd.Endpoints { @@ -427,33 +435,25 @@ func (sd *ServiceData) HasStreamingEndpoint() bool { // analyze creates the data necessary to render the code of the given service. func (ServicesData) analyze(gs *expr.GRPCServiceExpr) *ServiceData { - var ( - sd *ServiceData - seen, imported map[string]struct{} - svcVarN string - - svc = service.Services.Get(gs.Name()) - scope = codegen.NewNameScope() - pkg = codegen.SnakeCase(codegen.Goify(svc.Name, false)) + pbPkgName - ) - { - svcVarN = scope.HashedUnique(gs.ServiceExpr, codegen.Goify(svc.Name, true)) - sd = &ServiceData{ - Service: svc, - Name: svcVarN, - Description: svc.Description, - PkgName: pkg, - ServerStruct: "Server", - ClientStruct: "Client", - ServerInit: "New", - ClientInit: "NewClient", - ServerInterface: svcVarN + "Server", - ClientInterface: svcVarN + "Client", - ClientInterfaceInit: fmt.Sprintf("%s.New%sClient", pkg, svcVarN), - Scope: scope, - } - seen, imported = make(map[string]struct{}), make(map[string]struct{}) + svc := service.Services.Get(gs.Name()) + scope := codegen.NewNameScope() + pkg := codegen.SnakeCase(codegen.Goify(svc.Name, false)) + pbPkgName + svcVarN := scope.HashedUnique(gs.ServiceExpr, codegen.Goify(svc.Name, true)) + sd := &ServiceData{ + Service: svc, + Name: svcVarN, + Description: svc.Description, + PkgName: pkg, + ServerStruct: "Server", + ClientStruct: "Client", + ServerInit: "New", + ClientInit: "NewClient", + ServerInterface: svcVarN + "Server", + ClientInterface: svcVarN + "Client", + ClientInterfaceInit: fmt.Sprintf("%s.New%sClient", pkg, svcVarN), + Scope: scope, } + seen, imported := make(map[string]struct{}), make(map[string]struct{}) for _, e := range gs.GRPCEndpoints { // convert request and response types to protocol buffer message types e.Request = makeProtoBufMessage(e.Request, protoBufify(e.Name()+"_request", true, true), sd) @@ -504,102 +504,84 @@ func (ServicesData) analyze(gs *expr.GRPCServiceExpr) *ServiceData { payloadRef string resultRef string viewedResultRef string - errors []*ErrorData - - md = svc.Method(e.Name()) ) - { - if e.MethodExpr.Payload.Type != expr.Empty { - payloadRef = svc.Scope.GoFullTypeRef(e.MethodExpr.Payload, - pkgWithDefault(md.PayloadLoc, svc.PkgName)) - } - if e.MethodExpr.Result.Type != expr.Empty { - resultRef = svc.Scope.GoFullTypeRef(e.MethodExpr.Result, - pkgWithDefault(md.ResultLoc, svc.PkgName)) - } - if md.ViewedResult != nil { - viewedResultRef = md.ViewedResult.FullRef - } - errors = buildErrorsData(e, sd) - for _, er := range e.GRPCErrors { - if er.ErrorExpr.Type == expr.ErrorResult || !expr.IsObject(er.ErrorExpr.Type) { - continue - } - collect(er.Response.Message) + md := svc.Method(e.Name()) + if e.MethodExpr.Payload.Type != expr.Empty { + payloadRef = svc.Scope.GoFullTypeRef(e.MethodExpr.Payload, + pkgWithDefault(md.PayloadLoc, svc.PkgName)) + } + if e.MethodExpr.Result.Type != expr.Empty { + resultRef = svc.Scope.GoFullTypeRef(e.MethodExpr.Result, + pkgWithDefault(md.ResultLoc, svc.PkgName)) + } + if md.ViewedResult != nil { + viewedResultRef = md.ViewedResult.FullRef + } + errors := buildErrorsData(e, sd) + for _, er := range e.GRPCErrors { + if er.ErrorExpr.Type == expr.ErrorResult || !expr.IsObject(er.ErrorExpr.Type) { + continue } + collect(er.Response.Message) } // build request data - var ( - request *RequestData - reqMD []*MetadataData - ) - { - reqMD = extractMetadata(e.Metadata, e.MethodExpr.Payload, svc.Scope) - request = &RequestData{ - Description: e.Request.Description, - Metadata: reqMD, - ServerConvert: buildRequestConvertData(e.Request, e.MethodExpr.Payload, reqMD, e, sd, true), - ClientConvert: buildRequestConvertData(e.Request, e.MethodExpr.Payload, reqMD, e, sd, false), - } - if obj := expr.AsObject(e.Request.Type); (obj != nil && len(*obj) > 0) || expr.IsUnion(e.Request.Type) { - // add the request message as the first argument to the CLI - request.CLIArgs = append(request.CLIArgs, &InitArgData{ - Name: "message", - Ref: "message", - TypeName: protoBufGoFullTypeName(e.Request, sd.PkgName, sd.Scope), - TypeRef: protoBufGoFullTypeRef(e.Request, sd.PkgName, sd.Scope), - Example: e.Request.Example(expr.Root.API.ExampleGenerator), - }) - } - // pass the metadata as arguments to client CLI args - for _, m := range reqMD { - request.CLIArgs = append(request.CLIArgs, &InitArgData{ - Name: m.VarName, - Ref: m.VarName, - FieldName: m.FieldName, - FieldType: m.FieldType, - TypeName: m.TypeName, - TypeRef: m.TypeRef, - Type: m.Type, - Pointer: m.Pointer, - Required: m.Required, - Validate: m.Validate, - Example: m.Example, - DefaultValue: m.DefaultValue, - }) - } - if e.StreamingRequest.Type != expr.Empty { - request.Message = collect(e.StreamingRequest) - } else { - request.Message = collect(e.Request) - } + reqMD := extractMetadata(e.Metadata, e.MethodExpr.Payload, svc.Scope) + request := &RequestData{ + Description: e.Request.Description, + Metadata: reqMD, + ServerConvert: buildRequestConvertData(e.Request, e.MethodExpr.Payload, reqMD, e, sd, true), + ClientConvert: buildRequestConvertData(e.Request, e.MethodExpr.Payload, reqMD, e, sd, false), + } + if obj := expr.AsObject(e.Request.Type); (obj != nil && len(*obj) > 0) || expr.IsUnion(e.Request.Type) { + // add the request message as the first argument to the CLI + request.CLIArgs = append(request.CLIArgs, &InitArgData{ + Name: "message", + Ref: "message", + TypeName: protoBufGoFullTypeName(e.Request, sd.PkgName, sd.Scope), + TypeRef: protoBufGoFullTypeRef(e.Request, sd.PkgName, sd.Scope), + Example: e.Request.Example(expr.Root.API.ExampleGenerator), + }) + } + // pass the metadata as arguments to client CLI args + for _, m := range reqMD { + request.CLIArgs = append(request.CLIArgs, &InitArgData{ + Name: m.VarName, + Ref: m.VarName, + FieldName: m.FieldName, + FieldType: m.FieldType, + TypeName: m.TypeName, + TypeRef: m.TypeRef, + Type: m.Type, + Pointer: m.Pointer, + Required: m.Required, + Validate: m.Validate, + Example: m.Example, + DefaultValue: m.DefaultValue, + }) + } + if e.StreamingRequest.Type != expr.Empty { + request.Message = collect(e.StreamingRequest) + } else { + request.Message = collect(e.Request) } // build response data - var ( - response *ResponseData - hdrs []*MetadataData - trlrs []*MetadataData - - result, svcCtx = resultContext(e, sd) - ) - { - hdrs = extractMetadata(e.Response.Headers, result, svc.Scope) - trlrs = extractMetadata(e.Response.Trailers, result, svc.Scope) - response = &ResponseData{ - StatusCode: statusCodeToGRPCConst(e.Response.StatusCode), - Description: e.Response.Description, - Headers: hdrs, - Trailers: trlrs, - ServerConvert: buildResponseConvertData(e.Response.Message, result, svcCtx, hdrs, trlrs, e, sd, true), - ClientConvert: buildResponseConvertData(e.Response.Message, result, svcCtx, hdrs, trlrs, e, sd, false), - } - // If the endpoint is a streaming endpoint, no message is returned - // by gRPC. Hence, no need to set response message. - if e.Response.Message.Type != expr.Empty || !e.MethodExpr.IsStreaming() { - response.Message = collect(e.Response.Message) - } + result, svcCtx := resultContext(e, sd) + hdrs := extractMetadata(e.Response.Headers, result, svc.Scope) + trlrs := extractMetadata(e.Response.Trailers, result, svc.Scope) + response := &ResponseData{ + StatusCode: statusCodeToGRPCConst(e.Response.StatusCode), + Description: e.Response.Description, + Headers: hdrs, + Trailers: trlrs, + ServerConvert: buildResponseConvertData(e.Response.Message, result, svcCtx, hdrs, trlrs, e, sd, true), + ClientConvert: buildResponseConvertData(e.Response.Message, result, svcCtx, hdrs, trlrs, e, sd, false), + } + // If the endpoint is a streaming endpoint, no message is returned + // by gRPC. Hence, no need to set response message. + if e.Response.Message.Type != expr.Empty || !e.MethodExpr.IsStreaming() { + response.Message = collect(e.Response.Message) } // gather security requirements @@ -607,17 +589,15 @@ func (ServicesData) analyze(gs *expr.GRPCServiceExpr) *ServiceData { msgSch service.SchemesData metSch service.SchemesData ) - { - for _, req := range e.Requirements { - for _, sch := range req.Schemes { - s := md.Requirements.Scheme(sch.SchemeName).Dup() - s.In = sch.In - switch s.In { - case "message": - msgSch = msgSch.Append(s) - default: - metSch = metSch.Append(s) - } + for _, req := range e.Requirements { + for _, sch := range req.Schemes { + s := md.Requirements.Scheme(sch.SchemeName).Dup() + s.In = sch.In + switch s.In { + case "message": + msgSch = msgSch.Append(s) + default: + metSch = metSch.Append(s) } } } @@ -779,7 +759,7 @@ func collectValidations(att *expr.AttributeExpr, attName string, ctx *codegen.At switch dt := att.Type.(type) { case expr.UserType: if expr.IsPrimitive(dt) { - // Alias type - validation is generatd inline in parent type validation code. + // Alias type - validation is generate inline in parent type validation code. return } vtx := protoBufTypeContext(sd.PkgName, sd.Scope, false) @@ -858,35 +838,29 @@ func buildRequestConvertData(request, payload *expr.AttributeExpr, md []*Metadat return nil } - var ( - svc = sd.Service - pkg = pkgWithDefault(svc.Method(e.MethodExpr.Name).PayloadLoc, svc.PkgName) - svcCtx = serviceTypeContext(pkg, svc.Scope) - ) - + svc := sd.Service + pkg := pkgWithDefault(svc.Method(e.MethodExpr.Name).PayloadLoc, svc.PkgName) + svcCtx := serviceTypeContext(pkg, svc.Scope) if svr { // server side - var data *InitData - { - data = buildInitData(request, payload, "message", "v", svcCtx, false, svr, false, sd) - data.Name = fmt.Sprintf("New%sPayload", codegen.Goify(e.Name(), true)) - data.Description = fmt.Sprintf("%s builds the payload of the %q endpoint of the %q service from the gRPC request type.", data.Name, e.Name(), svc.Name) - for _, m := range md { - // pass the metadata as arguments to payload constructor in server - data.Args = append(data.Args, &InitArgData{ - Name: m.VarName, - Ref: m.VarName, - FieldName: m.FieldName, - FieldType: m.FieldType, - TypeName: m.TypeName, - TypeRef: m.TypeRef, - Type: m.Type, - Pointer: m.Pointer, - Required: m.Required, - Validate: m.Validate, - Example: m.Example, - }) - } + data := buildInitData(request, payload, "message", "v", svcCtx, false, svr, false, sd) + data.Name = fmt.Sprintf("New%sPayload", codegen.Goify(e.Name(), true)) + data.Description = fmt.Sprintf("%s builds the payload of the %q endpoint of the %q service from the gRPC request type.", data.Name, e.Name(), svc.Name) + for _, m := range md { + // pass the metadata as arguments to payload constructor in server + data.Args = append(data.Args, &InitArgData{ + Name: m.VarName, + Ref: m.VarName, + FieldName: m.FieldName, + FieldType: m.FieldType, + TypeName: m.TypeName, + TypeRef: m.TypeRef, + Type: m.Type, + Pointer: m.Pointer, + Required: m.Required, + Validate: m.Validate, + Example: m.Example, + }) } return &ConvertData{ SrcName: protoBufGoFullTypeName(request, sd.PkgName, sd.Scope), @@ -899,14 +873,8 @@ func buildRequestConvertData(request, payload *expr.AttributeExpr, md []*Metadat } // client side - - var ( - data *InitData - ) - { - data = buildInitData(payload, request, "payload", "message", svcCtx, true, svr, false, sd) - data.Description = fmt.Sprintf("%s builds the gRPC request type from the payload of the %q endpoint of the %q service.", data.Name, e.Name(), svc.Name) - } + data := buildInitData(payload, request, "payload", "message", svcCtx, true, svr, false, sd) + data.Description = fmt.Sprintf("%s builds the gRPC request type from the payload of the %q endpoint of the %q service.", data.Name, e.Name(), svc.Name) return &ConvertData{ SrcName: svc.Scope.GoFullTypeName(payload, pkg), SrcRef: svc.Scope.GoFullTypeRef(payload, pkg), @@ -928,19 +896,11 @@ func buildResponseConvertData(response, result *expr.AttributeExpr, svcCtx *code if !svr && (e.MethodExpr.IsStreaming() || isEmpty(e.MethodExpr.Result.Type)) { return nil } - - var ( - svc = sd.Service - ) - + svc := sd.Service if svr { // server side - - var data *InitData - { - data = buildInitData(result, response, "result", "message", svcCtx, true, svr, false, sd) - data.Description = fmt.Sprintf("%s builds the gRPC response type from the result of the %q endpoint of the %q service.", data.Name, e.Name(), svc.Name) - } + data := buildInitData(result, response, "result", "message", svcCtx, true, svr, false, sd) + data.Description = fmt.Sprintf("%s builds the gRPC response type from the result of the %q endpoint of the %q service.", data.Name, e.Name(), svc.Name) return &ConvertData{ SrcName: svcCtx.Scope.Name(result, svcCtx.Pkg(result), svcCtx.Pointer, svcCtx.UseDefault), SrcRef: svcCtx.Scope.Ref(result, svcCtx.Pkg(result)), @@ -951,44 +911,40 @@ func buildResponseConvertData(response, result *expr.AttributeExpr, svcCtx *code } // client side - - var data *InitData - { - data = buildInitData(response, result, "message", "result", svcCtx, false, svr, false, sd) - data.Name = fmt.Sprintf("New%sResult", codegen.Goify(e.Name(), true)) - data.Description = fmt.Sprintf("%s builds the result type of the %q endpoint of the %q service from the gRPC response type.", data.Name, e.Name(), svc.Name) - for _, m := range hdrs { - // pass the headers as arguments to result constructor in client - data.Args = append(data.Args, &InitArgData{ - Name: m.VarName, - Ref: m.VarName, - FieldName: m.FieldName, - FieldType: m.FieldType, - TypeName: m.TypeName, - TypeRef: m.TypeRef, - Type: m.Type, - Pointer: m.Pointer, - Required: m.Required, - Validate: m.Validate, - Example: m.Example, - }) - } - for _, m := range trlrs { - // pass the trailers as arguments to result constructor in client - data.Args = append(data.Args, &InitArgData{ - Name: m.VarName, - Ref: m.VarName, - FieldName: m.FieldName, - FieldType: m.FieldType, - TypeName: m.TypeName, - TypeRef: m.TypeRef, - Type: m.Type, - Pointer: m.Pointer, - Required: m.Required, - Validate: m.Validate, - Example: m.Example, - }) - } + data := buildInitData(response, result, "message", "result", svcCtx, false, svr, false, sd) + data.Name = fmt.Sprintf("New%sResult", codegen.Goify(e.Name(), true)) + data.Description = fmt.Sprintf("%s builds the result type of the %q endpoint of the %q service from the gRPC response type.", data.Name, e.Name(), svc.Name) + for _, m := range hdrs { + // pass the headers as arguments to result constructor in client + data.Args = append(data.Args, &InitArgData{ + Name: m.VarName, + Ref: m.VarName, + FieldName: m.FieldName, + FieldType: m.FieldType, + TypeName: m.TypeName, + TypeRef: m.TypeRef, + Type: m.Type, + Pointer: m.Pointer, + Required: m.Required, + Validate: m.Validate, + Example: m.Example, + }) + } + for _, m := range trlrs { + // pass the trailers as arguments to result constructor in client + data.Args = append(data.Args, &InitArgData{ + Name: m.VarName, + Ref: m.VarName, + FieldName: m.FieldName, + FieldType: m.FieldType, + TypeName: m.TypeName, + TypeRef: m.TypeRef, + Type: m.Type, + Pointer: m.Pointer, + Required: m.Required, + Validate: m.Validate, + Example: m.Example, + }) } return &ConvertData{ SrcName: protoBufGoFullTypeName(response, sd.PkgName, sd.Scope), @@ -1010,53 +966,40 @@ func buildResponseConvertData(response, result *expr.AttributeExpr, svcCtx *code // proto if true indicates the target type is a protocol buffer type // svr if true indicates the code is generated for conversion server side func buildInitData(source, target *expr.AttributeExpr, sourceVar, targetVar string, svcCtx *codegen.AttributeContext, proto, _, usesrc bool, sd *ServiceData) *InitData { - var ( - name string - isStruct bool - code string - helpers []*codegen.TransformFunctionData - args []*InitArgData - err error - srcCtx *codegen.AttributeContext - tgtCtx *codegen.AttributeContext - - // pbCtx = protoBufTypeContext(sd.PkgName, sd.Scope, proto && svr || !proto && !svr) - pbCtx = protoBufTypeContext(sd.PkgName, sd.Scope, false) - ) - { - name = "New" - srcCtx = pbCtx - tgtCtx = svcCtx - if proto { - srcCtx = svcCtx - tgtCtx = pbCtx - name += "Proto" - } - isStruct = expr.IsObject(target.Type) || expr.IsUnion(target.Type) - if _, ok := source.Type.(expr.UserType); ok && usesrc { - name += protoBufGoTypeName(source, sd.Scope) - } - n := protoBufGoTypeName(target, sd.Scope) - if !isStruct { - // If target is array, map, or primitive the name will be suffixed with - // the definition (e.g int, []string, map[int]string) which is incorrect. - n = protoBufGoTypeName(source, sd.Scope) - } - name += n - code, helpers, err = protoBufTransform(source, target, sourceVar, targetVar, srcCtx, tgtCtx, proto, true) - if err != nil { - panic(err) // bug - } - sd.transformHelpers = codegen.AppendHelpers(sd.transformHelpers, helpers) - if (!proto && !isEmpty(source.Type)) || (proto && !isEmpty(target.Type)) { - args = []*InitArgData{{ - Name: sourceVar, - Ref: sourceVar, - TypeName: srcCtx.Scope.Name(source, srcCtx.Pkg(source), srcCtx.Pointer, srcCtx.UseDefault), - TypeRef: srcCtx.Scope.Ref(source, srcCtx.Pkg(source)), - Example: source.Example(expr.Root.API.ExampleGenerator), - }} - } + pbCtx := protoBufTypeContext(sd.PkgName, sd.Scope, false) + name := "New" + srcCtx := pbCtx + tgtCtx := svcCtx + if proto { + srcCtx = svcCtx + tgtCtx = pbCtx + name += "Proto" + } + isStruct := expr.IsObject(target.Type) || expr.IsUnion(target.Type) + if _, ok := source.Type.(expr.UserType); ok && usesrc { + name += protoBufGoTypeName(source, sd.Scope) + } + n := protoBufGoTypeName(target, sd.Scope) + if !isStruct { + // If target is array, map, or primitive the name will be suffixed with + // the definition (e.g int, []string, map[int]string) which is incorrect. + n = protoBufGoTypeName(source, sd.Scope) + } + name += n + code, helpers, err := protoBufTransform(source, target, sourceVar, targetVar, srcCtx, tgtCtx, proto, true) + if err != nil { + panic(err) // bug + } + sd.transformHelpers = codegen.AppendHelpers(sd.transformHelpers, helpers) + var args []*InitArgData + if (!proto && !isEmpty(source.Type)) || (proto && !isEmpty(target.Type)) { + args = []*InitArgData{{ + Name: sourceVar, + Ref: sourceVar, + TypeName: srcCtx.Scope.Name(source, srcCtx.Pkg(source), srcCtx.Pointer, srcCtx.UseDefault), + TypeRef: srcCtx.Scope.Ref(source, srcCtx.Pkg(source)), + Example: source.Example(expr.Root.API.ExampleGenerator), + }} } return &InitData{ Name: name, @@ -1073,21 +1016,14 @@ func buildInitData(source, target *expr.AttributeExpr, sourceVar, targetVar stri // endpoint expression. The response message for each error response are // inferred from the method's error expression if not specified explicitly. func buildErrorsData(e *expr.GRPCEndpointExpr, sd *ServiceData) []*ErrorData { - var ( - errors []*ErrorData - - svc = sd.Service - ) - errors = make([]*ErrorData, 0, len(e.GRPCErrors)) + svc := sd.Service + errors := make([]*ErrorData, 0, len(e.GRPCErrors)) for _, v := range e.GRPCErrors { - var responseData *ResponseData - { - responseData = &ResponseData{ - StatusCode: statusCodeToGRPCConst(v.Response.StatusCode), - Description: v.Response.Description, - ServerConvert: buildErrorConvertData(v, e, sd, true), - ClientConvert: buildErrorConvertData(v, e, sd, false), - } + responseData := &ResponseData{ + StatusCode: statusCodeToGRPCConst(v.Response.StatusCode), + Description: v.Response.Description, + ServerConvert: buildErrorConvertData(v, e, sd, true), + ClientConvert: buildErrorConvertData(v, e, sd, false), } errorLoc := svc.Method(e.MethodExpr.Name).ErrorLocs[v.Name] errors = append(errors, &ErrorData{ @@ -1105,20 +1041,13 @@ func buildErrorConvertData(ge *expr.GRPCErrorExpr, e *expr.GRPCEndpointExpr, sd if ge.ErrorExpr.Type == expr.ErrorResult || !expr.IsObject(ge.ErrorExpr.Type) { return nil } - var ( - svc = sd.Service - svcCtx = serviceTypeContext(svc.PkgName, svc.Scope) - ) - + svc := sd.Service + svcCtx := serviceTypeContext(svc.PkgName, svc.Scope) if svr { // server side - - var data *InitData - { - data = buildInitData(ge.ErrorExpr.AttributeExpr, ge.Response.Message, "er", "message", svcCtx, true, svr, false, sd) - data.Name = fmt.Sprintf("New%s%sError", codegen.Goify(e.Name(), true), codegen.Goify(ge.Name, true)) - data.Description = fmt.Sprintf("%s builds the gRPC error response type from the error of the %q endpoint of the %q service.", data.Name, e.Name(), svc.Name) - } + data := buildInitData(ge.ErrorExpr.AttributeExpr, ge.Response.Message, "er", "message", svcCtx, true, svr, false, sd) + data.Name = fmt.Sprintf("New%s%sError", codegen.Goify(e.Name(), true), codegen.Goify(ge.Name, true)) + data.Description = fmt.Sprintf("%s builds the gRPC error response type from the error of the %q endpoint of the %q service.", data.Name, e.Name(), svc.Name) return &ConvertData{ SrcName: svcCtx.Scope.Name(ge.ErrorExpr.AttributeExpr, svcCtx.Pkg(ge.ErrorExpr.AttributeExpr), svcCtx.Pointer, svcCtx.UseDefault), SrcRef: svcCtx.Scope.Ref(ge.ErrorExpr.AttributeExpr, svcCtx.Pkg(ge.ErrorExpr.AttributeExpr)), @@ -1129,13 +1058,9 @@ func buildErrorConvertData(ge *expr.GRPCErrorExpr, e *expr.GRPCEndpointExpr, sd } // client side - - var data *InitData - { - data = buildInitData(ge.Response.Message, ge.ErrorExpr.AttributeExpr, "message", "er", svcCtx, false, svr, false, sd) - data.Name = fmt.Sprintf("New%s%sError", codegen.Goify(e.Name(), true), codegen.Goify(ge.Name, true)) - data.Description = fmt.Sprintf("%s builds the error type of the %q endpoint of the %q service from the gRPC error response type.", data.Name, e.Name(), svc.Name) - } + data := buildInitData(ge.Response.Message, ge.ErrorExpr.AttributeExpr, "message", "er", svcCtx, false, svr, false, sd) + data.Name = fmt.Sprintf("New%s%sError", codegen.Goify(e.Name(), true), codegen.Goify(ge.Name, true)) + data.Description = fmt.Sprintf("%s builds the error type of the %q endpoint of the %q service from the gRPC error response type.", data.Name, e.Name(), svc.Name) return &ConvertData{ SrcName: protoBufGoFullTypeName(ge.Response.Message, sd.PkgName, sd.Scope), SrcRef: protoBufGoFullTypeRef(ge.Response.Message, sd.PkgName, sd.Scope), @@ -1151,112 +1076,123 @@ func buildErrorConvertData(ge *expr.GRPCErrorExpr, e *expr.GRPCEndpointExpr, sd // svr param indicates that the stream data is built for the server. func buildStreamData(e *expr.GRPCEndpointExpr, sd *ServiceData, svr bool) *StreamData { var ( - varn string - intName string - svcInt string - sendName string - sendDesc string - sendRef string - sendConvert *ConvertData - recvName string - recvDesc string - recvRef string - recvConvert *ConvertData - mustClose bool - typ string - - svc = sd.Service - ed = sd.Endpoint(e.Name()) - md = ed.Method - svcCtx = serviceTypeContext(svc.PkgName, svc.Scope) - result, resCtx = resultContext(e, sd) + varn string + intName string + svcInt string + sendName string + sendDesc string + sendWithContextName string + sendWithContextDesc string + sendRef string + sendConvert *ConvertData + recvName string + recvDesc string + recvWithContextName string + recvWithContextDesc string + recvRef string + recvConvert *ConvertData + mustClose bool + typ string ) - { - resVar := "result" - if md.ViewedResult != nil { - resVar = "vresult" - } - if svr { - typ = "server" - varn = md.ServerStream.VarName - intName = fmt.Sprintf("%s.%s_%sServer", sd.PkgName, svc.StructName, md.VarName) - svcInt = fmt.Sprintf("%s.%s", svc.PkgName, md.ServerStream.Interface) - if e.MethodExpr.Result.Type != expr.Empty { - sendName = md.ServerStream.SendName - sendRef = ed.ResultRef - sendConvert = &ConvertData{ - SrcName: resCtx.Scope.Name(result, resCtx.Pkg(result), resCtx.Pointer, resCtx.UseDefault), - SrcRef: resCtx.Scope.Ref(result, resCtx.Pkg(result)), - TgtName: protoBufGoFullTypeName(e.Response.Message, sd.PkgName, sd.Scope), - TgtRef: protoBufGoFullTypeRef(e.Response.Message, sd.PkgName, sd.Scope), - Init: buildInitData(result, e.Response.Message, resVar, "v", resCtx, true, svr, true, sd), - } - } - if e.MethodExpr.StreamingPayload.Type != expr.Empty { - recvName = md.ServerStream.RecvName - recvRef = svcCtx.Scope.Ref(e.MethodExpr.StreamingPayload, svcCtx.Pkg(e.MethodExpr.StreamingPayload)) - recvConvert = &ConvertData{ - SrcName: protoBufGoFullTypeName(e.StreamingRequest, sd.PkgName, sd.Scope), - SrcRef: protoBufGoFullTypeRef(e.StreamingRequest, sd.PkgName, sd.Scope), - TgtName: svcCtx.Scope.Name(e.MethodExpr.StreamingPayload, svcCtx.Pkg(e.MethodExpr.StreamingPayload), svcCtx.Pointer, svcCtx.UseDefault), - TgtRef: recvRef, - Init: buildInitData(e.StreamingRequest, e.MethodExpr.StreamingPayload, "v", "spayload", svcCtx, false, svr, true, sd), - Validation: addValidation(e.StreamingRequest, "stream", sd, true), - } - } - mustClose = md.ServerStream.MustClose - } else { - typ = "client" - varn = md.ClientStream.VarName - intName = fmt.Sprintf("%s.%s_%sClient", sd.PkgName, svc.StructName, md.VarName) - svcInt = fmt.Sprintf("%s.%s", svc.PkgName, md.ClientStream.Interface) - if e.MethodExpr.StreamingPayload.Type != expr.Empty { - sendName = md.ClientStream.SendName - sendRef = svcCtx.Scope.Ref(e.MethodExpr.StreamingPayload, svcCtx.Pkg(e.MethodExpr.StreamingPayload)) - sendConvert = &ConvertData{ - SrcName: svcCtx.Scope.Name(e.MethodExpr.StreamingPayload, svcCtx.Pkg(e.MethodExpr.StreamingPayload), svcCtx.Pointer, svcCtx.UseDefault), - SrcRef: sendRef, - TgtName: protoBufGoFullTypeName(e.StreamingRequest, sd.PkgName, sd.Scope), - TgtRef: protoBufGoFullTypeRef(e.StreamingRequest, sd.PkgName, sd.Scope), - Init: buildInitData(e.MethodExpr.StreamingPayload, e.StreamingRequest, "spayload", "v", svcCtx, true, svr, true, sd), - } + svc := sd.Service + ed := sd.Endpoint(e.Name()) + md := ed.Method + svcCtx := serviceTypeContext(svc.PkgName, svc.Scope) + result, resCtx := resultContext(e, sd) + resVar := "result" + if md.ViewedResult != nil { + resVar = "vresult" + } + if svr { + typ = "server" + varn = md.ServerStream.VarName + intName = fmt.Sprintf("%s.%s_%sServer", sd.PkgName, svc.StructName, md.VarName) + svcInt = fmt.Sprintf("%s.%s", svc.PkgName, md.ServerStream.Interface) + if e.MethodExpr.Result.Type != expr.Empty { + sendName = md.ServerStream.SendName + sendRef = ed.ResultRef + sendWithContextName = md.ServerStream.SendWithContextName + sendConvert = &ConvertData{ + SrcName: resCtx.Scope.Name(result, resCtx.Pkg(result), resCtx.Pointer, resCtx.UseDefault), + SrcRef: resCtx.Scope.Ref(result, resCtx.Pkg(result)), + TgtName: protoBufGoFullTypeName(e.Response.Message, sd.PkgName, sd.Scope), + TgtRef: protoBufGoFullTypeRef(e.Response.Message, sd.PkgName, sd.Scope), + Init: buildInitData(result, e.Response.Message, resVar, "v", resCtx, true, svr, true, sd), } - if e.MethodExpr.Result.Type != expr.Empty { - recvName = md.ClientStream.RecvName - recvRef = ed.ResultRef - recvConvert = &ConvertData{ - SrcName: protoBufGoFullTypeName(e.Response.Message, sd.PkgName, sd.Scope), - SrcRef: protoBufGoFullTypeRef(e.Response.Message, sd.PkgName, sd.Scope), - TgtName: resCtx.Scope.Name(result, resCtx.Pkg(result), resCtx.Pointer, resCtx.UseDefault), - TgtRef: resCtx.Scope.Ref(result, resCtx.Pkg(result)), - Init: buildInitData(e.Response.Message, result, "v", resVar, resCtx, false, svr, true, sd), - Validation: addValidation(e.Response.Message, "stream", sd, false), - } + } + if e.MethodExpr.StreamingPayload.Type != expr.Empty { + recvName = md.ServerStream.RecvName + recvWithContextName = md.ServerStream.RecvWithContextName + recvRef = svcCtx.Scope.Ref(e.MethodExpr.StreamingPayload, svcCtx.Pkg(e.MethodExpr.StreamingPayload)) + recvConvert = &ConvertData{ + SrcName: protoBufGoFullTypeName(e.StreamingRequest, sd.PkgName, sd.Scope), + SrcRef: protoBufGoFullTypeRef(e.StreamingRequest, sd.PkgName, sd.Scope), + TgtName: svcCtx.Scope.Name(e.MethodExpr.StreamingPayload, svcCtx.Pkg(e.MethodExpr.StreamingPayload), svcCtx.Pointer, svcCtx.UseDefault), + TgtRef: recvRef, + Init: buildInitData(e.StreamingRequest, e.MethodExpr.StreamingPayload, "v", "spayload", svcCtx, false, svr, true, sd), + Validation: addValidation(e.StreamingRequest, "stream", sd, true), } - mustClose = md.ClientStream.MustClose } - if sendConvert != nil { - sendDesc = fmt.Sprintf("%s streams instances of %q to the %q endpoint gRPC stream.", sendName, sendConvert.TgtName, md.Name) + mustClose = md.ServerStream.MustClose + } else { + typ = "client" + varn = md.ClientStream.VarName + intName = fmt.Sprintf("%s.%s_%sClient", sd.PkgName, svc.StructName, md.VarName) + svcInt = fmt.Sprintf("%s.%s", svc.PkgName, md.ClientStream.Interface) + if e.MethodExpr.StreamingPayload.Type != expr.Empty { + sendName = md.ClientStream.SendName + sendWithContextName = md.ClientStream.SendWithContextName + sendRef = svcCtx.Scope.Ref(e.MethodExpr.StreamingPayload, svcCtx.Pkg(e.MethodExpr.StreamingPayload)) + sendConvert = &ConvertData{ + SrcName: svcCtx.Scope.Name(e.MethodExpr.StreamingPayload, svcCtx.Pkg(e.MethodExpr.StreamingPayload), svcCtx.Pointer, svcCtx.UseDefault), + SrcRef: sendRef, + TgtName: protoBufGoFullTypeName(e.StreamingRequest, sd.PkgName, sd.Scope), + TgtRef: protoBufGoFullTypeRef(e.StreamingRequest, sd.PkgName, sd.Scope), + Init: buildInitData(e.MethodExpr.StreamingPayload, e.StreamingRequest, "spayload", "v", svcCtx, true, svr, true, sd), + } } - if recvConvert != nil { - recvDesc = fmt.Sprintf("%s reads instances of %q from the %q endpoint gRPC stream.", recvName, recvConvert.SrcName, md.Name) + if e.MethodExpr.Result.Type != expr.Empty { + recvName = md.ClientStream.RecvName + recvWithContextName = md.ClientStream.RecvWithContextName + recvRef = ed.ResultRef + recvConvert = &ConvertData{ + SrcName: protoBufGoFullTypeName(e.Response.Message, sd.PkgName, sd.Scope), + SrcRef: protoBufGoFullTypeRef(e.Response.Message, sd.PkgName, sd.Scope), + TgtName: resCtx.Scope.Name(result, resCtx.Pkg(result), resCtx.Pointer, resCtx.UseDefault), + TgtRef: resCtx.Scope.Ref(result, resCtx.Pkg(result)), + Init: buildInitData(e.Response.Message, result, "v", resVar, resCtx, false, svr, true, sd), + Validation: addValidation(e.Response.Message, "stream", sd, false), + } } + mustClose = md.ClientStream.MustClose + } + if sendConvert != nil { + sendDesc = fmt.Sprintf("%s streams instances of %q to the %q endpoint gRPC stream.", sendName, sendConvert.TgtName, md.Name) + sendWithContextDesc = fmt.Sprintf("%s streams instances of %q to the %q endpoint gRPC stream with context.", sendWithContextName, sendConvert.TgtName, md.Name) + } + if recvConvert != nil { + recvDesc = fmt.Sprintf("%s reads instances of %q from the %q endpoint gRPC stream.", recvName, recvConvert.SrcName, md.Name) + recvWithContextDesc = fmt.Sprintf("%s reads instances of %q from the %q endpoint gRPC stream with context.", recvWithContextName, recvConvert.SrcName, md.Name) } return &StreamData{ - VarName: varn, - Type: typ, - Interface: intName, - ServiceInterface: svcInt, - Endpoint: ed, - SendName: sendName, - SendDesc: sendDesc, - SendRef: sendRef, - SendConvert: sendConvert, - RecvName: recvName, - RecvDesc: recvDesc, - RecvRef: recvRef, - RecvConvert: recvConvert, - MustClose: mustClose, + VarName: varn, + Type: typ, + Interface: intName, + ServiceInterface: svcInt, + Endpoint: ed, + SendName: sendName, + SendDesc: sendDesc, + SendWithContextName: sendWithContextName, + SendWithContextDesc: sendWithContextDesc, + SendRef: sendRef, + SendConvert: sendConvert, + RecvName: recvName, + RecvDesc: recvDesc, + RecvWithContextName: recvWithContextName, + RecvWithContextDesc: recvWithContextDesc, + RecvRef: recvRef, + RecvConvert: recvConvert, + MustClose: mustClose, } } @@ -1266,28 +1202,21 @@ func extractMetadata(a *expr.MappedAttributeExpr, service *expr.AttributeExpr, s var metadata []*MetadataData ctx := serviceTypeContext("", scope) codegen.WalkMappedAttr(a, func(name, elem string, required bool, c *expr.AttributeExpr) error { // nolint: errcheck - var ( - varn string - fieldName string - pointer bool - - arr = expr.AsArray(c.Type) - mp = expr.AsMap(c.Type) - typeRef = scope.GoTypeRef(unalias(c)) - ft = service.Type - ) - { - varn = scope.Name(codegen.Goify(name, false)) - fieldName = codegen.Goify(name, true) - if !expr.IsObject(service.Type) { - fieldName = "" - } else { - pointer = service.IsPrimitivePointer(name, true) - ft = service.Find(name).Type - } - if pointer { - typeRef = "*" + typeRef - } + arr := expr.AsArray(c.Type) + mp := expr.AsMap(c.Type) + typeRef := scope.GoTypeRef(unalias(c)) + ft := service.Type + varn := scope.Name(codegen.Goify(name, false)) + fieldName := codegen.Goify(name, true) + var pointer bool + if !expr.IsObject(service.Type) { + fieldName = "" + } else { + pointer = service.IsPrimitivePointer(name, true) + ft = service.Find(name).Type + } + if pointer { + typeRef = "*" + typeRef } metadata = append(metadata, &MetadataData{ Name: elem, diff --git a/vendor/goa.design/goa/v3/grpc/codegen/templates/client_endpoint_init.go.tpl b/vendor/goa.design/goa/v3/grpc/codegen/templates/client_endpoint_init.go.tpl index 392d7b2286..586b5867a7 100644 --- a/vendor/goa.design/goa/v3/grpc/codegen/templates/client_endpoint_init.go.tpl +++ b/vendor/goa.design/goa/v3/grpc/codegen/templates/client_endpoint_init.go.tpl @@ -24,12 +24,12 @@ func (c *{{ .ClientStruct }}) {{ .Method.VarName }}() goa.Endpoint { case *goapb.ErrorResponse: return nil, goagrpc.NewServiceError(message) default: - return nil, goa.Fault(err.Error()) + return nil, goa.Fault("%s", err.Error()) } {{- else }} - return nil, goa.Fault(err.Error()) + return nil, goa.Fault("%s", err.Error()) {{- end }} } return res, nil } -} \ No newline at end of file +} diff --git a/vendor/goa.design/goa/v3/grpc/codegen/templates/do_grpc_cli.go.tpl b/vendor/goa.design/goa/v3/grpc/codegen/templates/do_grpc_cli.go.tpl index 8802e20c69..bdc52ca3cb 100644 --- a/vendor/goa.design/goa/v3/grpc/codegen/templates/do_grpc_cli.go.tpl +++ b/vendor/goa.design/goa/v3/grpc/codegen/templates/do_grpc_cli.go.tpl @@ -3,7 +3,19 @@ func doGRPC(_, host string, _ int, _ bool) (goa.Endpoint, any, error) { if err != nil { fmt.Fprintf(os.Stderr, "could not connect to gRPC server at %s: %v\n", host, err) } - return cli.ParseEndpoint(conn) +{{- range .Services }} + {{- if .Service.ClientInterceptors }} + {{ .Service.VarName }}Interceptors := {{ $.InterceptorsPkg }}.New{{ .Service.StructName }}ClientInterceptors() + {{- end }} +{{- end }} + return cli.ParseEndpoint( + conn, +{{- range .Services }} + {{- if .Service.ClientInterceptors }} + {{ .Service.VarName }}Interceptors, + {{- end }} +{{- end }} + ) } {{ if eq .DefaultTransport.Type "grpc" }} diff --git a/vendor/goa.design/goa/v3/grpc/codegen/templates/parse_endpoint.go.tpl b/vendor/goa.design/goa/v3/grpc/codegen/templates/parse_endpoint.go.tpl index b7f3eed3ad..538dad4768 100644 --- a/vendor/goa.design/goa/v3/grpc/codegen/templates/parse_endpoint.go.tpl +++ b/vendor/goa.design/goa/v3/grpc/codegen/templates/parse_endpoint.go.tpl @@ -1,6 +1,14 @@ // ParseEndpoint returns the endpoint and payload as specified on the command // line. -func ParseEndpoint(cc *grpc.ClientConn, opts ...grpc.CallOption) (goa.Endpoint, any, error) { +func ParseEndpoint( + cc *grpc.ClientConn, +{{- range .Commands }} + {{- if .Interceptors }} + {{ .Interceptors.VarName }} {{ .Interceptors.PkgName }}.ClientInterceptors, + {{- end }} +{{- end }} + opts ...grpc.CallOption, +) (goa.Endpoint, any, error) { {{ .FlagsCode }} var ( data any @@ -13,9 +21,13 @@ func ParseEndpoint(cc *grpc.ClientConn, opts ...grpc.CallOption) (goa.Endpoint, case "{{ .Name }}": c := {{ .PkgName }}.NewClient(cc, opts...) switch epn { - {{- $pkgName := .PkgName }}{{ range .Subcommands }} + {{- $pkgName := .PkgName }} + {{ range .Subcommands }} case "{{ .Name }}": endpoint = c.{{ .MethodVarName }}() + {{- if .Interceptors }} + endpoint = {{ .Interceptors.PkgName }}.Wrap{{ .MethodVarName }}ClientEndpoint(endpoint, {{ .Interceptors.VarName }}) + {{- end }} {{- if .BuildFunction }} data, err = {{ $pkgName}}.{{ .BuildFunction.Name }}({{ range .BuildFunction.ActualParams }}*{{ . }}Flag, {{ end }}) {{- else if .Conversion }} @@ -31,4 +43,4 @@ func ParseEndpoint(cc *grpc.ClientConn, opts ...grpc.CallOption) (goa.Endpoint, } return endpoint, data, nil -} \ No newline at end of file +} diff --git a/vendor/goa.design/goa/v3/grpc/codegen/templates/stream_recv.go.tpl b/vendor/goa.design/goa/v3/grpc/codegen/templates/stream_recv.go.tpl index 593ce4de98..93215633a5 100644 --- a/vendor/goa.design/goa/v3/grpc/codegen/templates/stream_recv.go.tpl +++ b/vendor/goa.design/goa/v3/grpc/codegen/templates/stream_recv.go.tpl @@ -21,3 +21,8 @@ func (s *{{ .VarName }}) {{ .RecvName }}() ({{ .RecvRef }}, error) { return {{ .RecvConvert.Init.Name }}({{ range .RecvConvert.Init.Args }}{{ .Name }}, {{ end }}), nil {{- end }} } + +{{ comment .RecvWithContextDesc }} +func (s *{{ .VarName }}) {{ .RecvWithContextName }}(ctx context.Context) ({{ .RecvRef }}, error) { + return s.{{ .RecvName }}() +} diff --git a/vendor/goa.design/goa/v3/grpc/codegen/templates/stream_send.go.tpl b/vendor/goa.design/goa/v3/grpc/codegen/templates/stream_send.go.tpl index 7a66cea3d1..e873121a22 100644 --- a/vendor/goa.design/goa/v3/grpc/codegen/templates/stream_send.go.tpl +++ b/vendor/goa.design/goa/v3/grpc/codegen/templates/stream_send.go.tpl @@ -10,3 +10,8 @@ func (s *{{ .VarName }}) {{ .SendName }}(res {{ .SendRef }}) error { v := {{ .SendConvert.Init.Name }}({{ if and .Endpoint.Method.ViewedResult (eq .Type "server") }}vres.Projected{{ else }}res{{ end }}) return s.stream.{{ .SendName }}(v) } + +{{ comment .SendWithContextDesc }} +func (s *{{ .VarName }}) {{ .SendWithContextName }}(ctx context.Context, res {{ .SendRef }}) error { + return s.{{ .SendName }}(res) +} diff --git a/vendor/goa.design/goa/v3/http/codegen/client.go b/vendor/goa.design/goa/v3/http/codegen/client.go index 52e0248712..5d70b2ed8d 100644 --- a/vendor/goa.design/goa/v3/http/codegen/client.go +++ b/vendor/goa.design/goa/v3/http/codegen/client.go @@ -67,7 +67,7 @@ func clientFile(genpkg string, svc *expr.HTTPServiceExpr) *codegen.File { } sections = append(sections, &codegen.SectionTemplate{ - Name: "client-init", + Name: "http-client-init", Source: readTemplate("client_init"), Data: data, FuncMap: map[string]any{"hasWebSocket": hasWebSocket}, diff --git a/vendor/goa.design/goa/v3/http/codegen/client_cli.go b/vendor/goa.design/goa/v3/http/codegen/client_cli.go index 73a787e54a..da4fa238a8 100644 --- a/vendor/goa.design/goa/v3/http/codegen/client_cli.go +++ b/vendor/goa.design/goa/v3/http/codegen/client_cli.go @@ -24,7 +24,7 @@ type subcommandData struct { // MultipartFuncName is the name of the function used to render a multipart // request encoder. MultipartFuncName string - // MultipartFuncName is the name of the variabl used to render a multipart + // MultipartFuncName is the name of the variable used to render a multipart // request encoder. MultipartVarName string // StreamFlag is the flag used to identify the file to be streamed when @@ -87,7 +87,7 @@ func buildSubcommandData(sd *ServiceData, e *EndpointData) *subcommandData { flags, buildFunction := buildFlags(sd, e) sub := &subcommandData{ - SubcommandData: cli.BuildSubcommandData(sd.Service.Name, e.Method, buildFunction, flags), + SubcommandData: cli.BuildSubcommandData(sd.Service, e.Method, buildFunction, flags), } if e.MultipartRequestEncoder != nil { sub.MultipartVarName = e.MultipartRequestEncoder.VarName @@ -127,6 +127,13 @@ func endpointParser(genpkg string, root *expr.RootExpr, svr *expr.ServerExpr, da Path: genpkg + "/http/" + sd.Service.PathName + "/client", Name: sd.Service.PkgName + "c", }) + // Add interceptors import if service has client interceptors + if len(sd.Service.ClientInterceptors) > 0 { + specs = append(specs, &codegen.ImportSpec{ + Path: genpkg + "/" + sd.Service.PathName, + Name: sd.Service.PkgName, + }) + } } cliData := make([]*cli.CommandData, len(data)) diff --git a/vendor/goa.design/goa/v3/http/codegen/example_cli.go b/vendor/goa.design/goa/v3/http/codegen/example_cli.go index fe7b6e4968..c6d57c8340 100644 --- a/vendor/goa.design/goa/v3/http/codegen/example_cli.go +++ b/vendor/goa.design/goa/v3/http/codegen/example_cli.go @@ -7,6 +7,7 @@ import ( "goa.design/goa/v3/codegen" "goa.design/goa/v3/codegen/example" + "goa.design/goa/v3/codegen/service" "goa.design/goa/v3/expr" ) @@ -30,20 +31,10 @@ func exampleCLI(genpkg string, root *expr.RootExpr, svr *expr.ServerExpr) *codeg if _, err := os.Stat(path); !os.IsNotExist(err) { return nil // file already exists, skip it. } - var ( - rootPath string - apiPkg string - - scope = codegen.NewNameScope() - ) - { - // genpkg is created by path.Join so the separator is / regardless of operating system - idx := strings.LastIndex(genpkg, string("/")) - rootPath = "." - if idx > 0 { - rootPath = genpkg[:idx] - } - apiPkg = scope.Unique(strings.ToLower(codegen.Goify(root.API.Name, false)), "api") + idx := strings.LastIndex(genpkg, string("/")) + rootPath := "." + if idx > 0 { + rootPath = genpkg[:idx] } specs := []*codegen.ImportSpec{ {Path: "context"}, @@ -59,8 +50,17 @@ func exampleCLI(genpkg string, root *expr.RootExpr, svr *expr.ServerExpr) *codeg codegen.GoaImport(""), codegen.GoaNamedImport("http", "goahttp"), {Path: genpkg + "/http/cli/" + svrdata.Dir, Name: "cli"}, - {Path: rootPath, Name: apiPkg}, } + importScope := codegen.NewNameScope() + for _, svc := range root.Services { + data := service.Services.Get(svc.Name) + specs = append(specs, &codegen.ImportSpec{Path: genpkg + "/" + data.PkgName}) + importScope.Unique(data.PkgName) + } + interceptorsPkg := importScope.Unique("interceptors", "ex") + specs = append(specs, &codegen.ImportSpec{Path: rootPath + "/interceptors", Name: interceptorsPkg}) + apiPkg := importScope.Unique(strings.ToLower(codegen.Goify(root.API.Name, false)), "api") + specs = append(specs, &codegen.ImportSpec{Path: rootPath, Name: apiPkg}) var svcData []*ServiceData for _, svc := range svr.Services { @@ -73,6 +73,10 @@ func exampleCLI(genpkg string, root *expr.RootExpr, svr *expr.ServerExpr) *codeg { Name: "cli-http-start", Source: readTemplate("cli_start"), + Data: map[string]any{ + "Services": svcData, + "InterceptorsPkg": interceptorsPkg, + }, }, { Name: "cli-http-streaming", diff --git a/vendor/goa.design/goa/v3/http/codegen/openapi/json_schema.go b/vendor/goa.design/goa/v3/http/codegen/openapi/json_schema.go index e51658c3aa..ff25e3b47e 100644 --- a/vendor/goa.design/goa/v3/http/codegen/openapi/json_schema.go +++ b/vendor/goa.design/goa/v3/http/codegen/openapi/json_schema.go @@ -486,6 +486,9 @@ func buildAttributeSchema(api *expr.APIExpr, s *Schema, at *expr.AttributeExpr) s.Description = at.Description s.Example = at.Example(api.ExampleGenerator) s.Extensions = ExtensionsFromExpr(at.Meta) + if ap := AdditionalPropertiesFromExpr(at.Meta); ap != nil { + s.AdditionalProperties = ap + } initAttributeValidation(s, at) return s @@ -593,3 +596,12 @@ func MustGenerate(meta expr.MetaExpr) bool { } return true } + +// AdditionalPropertiesFromExpr extracts the OpenAPI additionalProperties. +func AdditionalPropertiesFromExpr(meta expr.MetaExpr) any { + m, ok := meta.Last("openapi:additionalProperties") + if ok && m == "false" { + return false + } + return nil +} diff --git a/vendor/goa.design/goa/v3/http/codegen/openapi/v3/types.go b/vendor/goa.design/goa/v3/http/codegen/openapi/v3/types.go index b96deabc61..5509dff4f3 100644 --- a/vendor/goa.design/goa/v3/http/codegen/openapi/v3/types.go +++ b/vendor/goa.design/goa/v3/http/codegen/openapi/v3/types.go @@ -8,6 +8,8 @@ import ( "strconv" "strings" + "github.com/gohugoio/hashstructure" + "goa.design/goa/v3/codegen" "goa.design/goa/v3/expr" "goa.design/goa/v3/http/codegen/openapi" @@ -264,6 +266,9 @@ func (sf *schemafier) schemafy(attr *expr.AttributeExpr, noref ...bool) *openapi s.Extensions = openapi.ExtensionsFromExpr(attr.Meta) // Validations + if ap := openapi.AdditionalPropertiesFromExpr(attr.Meta); ap != nil { + s.AdditionalProperties = ap + } val := attr.Validation if val == nil { return s @@ -376,7 +381,7 @@ func toString(val any) string { // identifiers. Structurally identical means same primitive types, arrays with // structurally equivalent element types, maps with structurally equivalent key // and value types or object with identical attribute names and structurally -// equivalent types and identical set of required attributes. +// equivalent types and identical set of validation rules. func (*schemafier) hashAttribute(att *expr.AttributeExpr, h hash.Hash64) uint64 { return *hashAttribute(att, h, make(map[string]*uint64)) } @@ -393,6 +398,7 @@ func hashAttribute(att *expr.AttributeExpr, h hash.Hash64, seen map[string]*uint } seen[t.Hash()] = res + hv := hashValidation(att.Validation, h) switch t.Kind() { case expr.ObjectKind: o := expr.AsObject(t) @@ -404,25 +410,26 @@ func hashAttribute(att *expr.AttributeExpr, h hash.Hash64, seen map[string]*uint vh := hashAttribute(m.Attribute, h, seen) *res = *res ^ orderedHash(kh, *vh, h) } - // Objects with a different set of required attributes should produce - // different hashes. - if att.Validation != nil { - for _, req := range att.Validation.Required { - rh := hashString(req, h) - *res = *res ^ rh - } + if hv != 0 { + *res = orderedHash(*res, hv, h) } case expr.ArrayKind: kh := hashString("[]", h) vh := hashAttribute(expr.AsArray(t).ElemType, h, seen) *res = orderedHash(kh, *vh, h) + if hv != 0 { + *res = orderedHash(*res, hv, h) + } case expr.MapKind: m := expr.AsMap(t) kh := hashAttribute(m.KeyType, h, seen) vh := hashAttribute(m.ElemType, h, seen) *res = orderedHash(*kh, *vh, h) + if hv != 0 { + *res = orderedHash(*res, hv, h) + } case expr.UserTypeKind: *res = *hashAttribute(t.(expr.UserType).Attribute(), h, seen) @@ -438,11 +445,34 @@ func hashAttribute(att *expr.AttributeExpr, h hash.Hash64, seen map[string]*uint default: // Primitives or Any *res = hashString(t.Name(), h) + if hv != 0 { + *res = orderedHash(*res, hv, h) + } } return res } +func hashValidation(val *expr.ValidationExpr, h hash.Hash64) uint64 { + // Note: we can't use hashstructure for attributes because it doesn't + // handle recursive structures. + if val == nil { + return 0 + } + + res, err := hashstructure.Hash(val, &hashstructure.HashOptions{ + Hasher: h, + ZeroNil: false, + IgnoreZeroValue: true, + SlicesAsSets: true, + }) + if err != nil { + // should really never happen (OOM maybe) + return 0 + } + return res +} + func hashString(s string, h hash.Hash64) uint64 { h.Reset() if _, err := h.Write([]byte(s)); err != nil { diff --git a/vendor/goa.design/goa/v3/http/codegen/server.go b/vendor/goa.design/goa/v3/http/codegen/server.go index a06fb247b6..c514baa223 100644 --- a/vendor/goa.design/goa/v3/http/codegen/server.go +++ b/vendor/goa.design/goa/v3/http/codegen/server.go @@ -64,8 +64,9 @@ func serverFile(genpkg string, svc *expr.HTTPServiceExpr) *codegen.File { codegen.Header(title, "server", imports), } - sections = append(sections, &codegen.SectionTemplate{Name: "server-struct", Source: readTemplate("server_struct"), Data: data}) - sections = append(sections, &codegen.SectionTemplate{Name: "server-mountpoint", Source: readTemplate("mount_point_struct"), Data: data}) + sections = append(sections, + &codegen.SectionTemplate{Name: "server-struct", Source: readTemplate("server_struct"), Data: data}, + &codegen.SectionTemplate{Name: "server-mountpoint", Source: readTemplate("mount_point_struct"), Data: data}) for _, e := range data.Endpoints { if e.MultipartRequestDecoder != nil { @@ -77,15 +78,17 @@ func serverFile(genpkg string, svc *expr.HTTPServiceExpr) *codegen.File { } } - sections = append(sections, &codegen.SectionTemplate{Name: "server-init", Source: readTemplate("server_init"), Data: data, FuncMap: funcs}) - sections = append(sections, &codegen.SectionTemplate{Name: "server-service", Source: readTemplate("server_service"), Data: data}) - sections = append(sections, &codegen.SectionTemplate{Name: "server-use", Source: readTemplate("server_use"), Data: data}) - sections = append(sections, &codegen.SectionTemplate{Name: "server-method-names", Source: readTemplate("server_method_names"), Data: data}) - sections = append(sections, &codegen.SectionTemplate{Name: "server-mount", Source: readTemplate("server_mount"), Data: data, FuncMap: funcs}) + sections = append(sections, + &codegen.SectionTemplate{Name: "server-init", Source: readTemplate("server_init"), Data: data, FuncMap: funcs}, + &codegen.SectionTemplate{Name: "server-service", Source: readTemplate("server_service"), Data: data}, + &codegen.SectionTemplate{Name: "server-use", Source: readTemplate("server_use"), Data: data}, + &codegen.SectionTemplate{Name: "server-method-names", Source: readTemplate("server_method_names"), Data: data}, + &codegen.SectionTemplate{Name: "server-mount", Source: readTemplate("server_mount"), Data: data, FuncMap: funcs}) for _, e := range data.Endpoints { - sections = append(sections, &codegen.SectionTemplate{Name: "server-handler", Source: readTemplate("server_handler"), Data: e}) - sections = append(sections, &codegen.SectionTemplate{Name: "server-handler-init", Source: readTemplate("server_handler_init"), FuncMap: funcs, Data: e}) + sections = append(sections, + &codegen.SectionTemplate{Name: "server-handler", Source: readTemplate("server_handler"), Data: e}, + &codegen.SectionTemplate{Name: "server-handler-init", Source: readTemplate("server_handler_init"), FuncMap: funcs, Data: e}) } if len(data.FileServers) > 0 { mappedFiles := make(map[string]string) diff --git a/vendor/goa.design/goa/v3/http/codegen/service_data.go b/vendor/goa.design/goa/v3/http/codegen/service_data.go index c1818960c9..8ac7288863 100644 --- a/vendor/goa.design/goa/v3/http/codegen/service_data.go +++ b/vendor/goa.design/goa/v3/http/codegen/service_data.go @@ -595,7 +595,7 @@ func (ServicesData) analyze(httpSvc *expr.HTTPServiceExpr) *ServiceData { scope := codegen.NewNameScope() scope.Unique("c") // 'c' is reserved as the client's receiver name. scope.Unique("v") // 'v' is reserved as the request builder payload argument name. - rd := &ServiceData{ + sd := &ServiceData{ Service: svc, ServerStruct: "Server", MountPointStruct: "MountPoint", @@ -641,7 +641,7 @@ func (ServicesData) analyze(httpSvc *expr.HTTPServiceExpr) *ServiceData { VarName: scope.Unique(codegen.Goify(s.FilePath, true)), ArgName: scope.Unique(fmt.Sprintf("fileSystem%s", codegen.Goify(s.FilePath, true))), } - rd.FileServers = append(rd.FileServers, data) + sd.FileServers = append(sd.FileServers, data) } for _, httpEndpoint := range httpSvc.HTTPEndpoints { @@ -672,10 +672,10 @@ func (ServicesData) analyze(httpSvc *expr.HTTPServiceExpr) *ServiceData { // Path params may override requiredness, need to check payload. pointer = httpEndpoint.MethodExpr.Payload.IsPrimitivePointer(arg, true) } - name := rd.Scope.Name(codegen.Goify(arg, false)) + name := sd.Scope.Name(codegen.Goify(arg, false)) var vcode string if att.Validation != nil { - ctx := httpContext("", rd.Scope, true, false) + ctx := httpContext("", sd.Scope, true, false) vcode = codegen.AttributeValidationCode(att, nil, ctx, true, expr.IsAlias(att.Type), name, arg) } initArgs[j] = &InitArgData{ @@ -686,8 +686,8 @@ func (ServicesData) analyze(httpSvc *expr.HTTPServiceExpr) *ServiceData { Description: att.Description, FieldName: codegen.Goify(arg, true), FieldType: patt.Type, - TypeName: rd.Scope.GoTypeName(att), - TypeRef: rd.Scope.GoTypeRef(att), + TypeName: sd.Scope.GoTypeName(att), + TypeRef: sd.Scope.GoTypeRef(att), Type: att.Type, Pointer: pointer, Required: true, @@ -727,7 +727,7 @@ func (ServicesData) analyze(httpSvc *expr.HTTPServiceExpr) *ServiceData { } } - payload := buildPayloadData(httpEndpoint, rd) + payload := buildPayloadData(httpEndpoint, sd) var ( reqs service.RequirementsData @@ -817,8 +817,8 @@ func (ServicesData) analyze(httpSvc *expr.HTTPServiceExpr) *ServiceData { ServiceVarName: svc.VarName, ServicePkgName: svc.PkgName, Payload: payload, - Result: buildResultData(httpEndpoint, rd), - Errors: buildErrorsData(httpEndpoint, rd), + Result: buildResultData(httpEndpoint, sd), + Errors: buildErrorsData(httpEndpoint, sd), HeaderSchemes: hsch, BodySchemes: bosch, QuerySchemes: qsch, @@ -837,7 +837,7 @@ func (ServicesData) analyze(httpSvc *expr.HTTPServiceExpr) *ServiceData { Requirements: reqs, } if httpEndpoint.MethodExpr.IsStreaming() { - initWebSocketData(ed, httpEndpoint, rd) + initWebSocketData(ed, httpEndpoint, sd) } if httpEndpoint.MultipartRequest { @@ -870,26 +870,26 @@ func (ServicesData) analyze(httpSvc *expr.HTTPServiceExpr) *ServiceData { } } - rd.Endpoints = append(rd.Endpoints, ed) + sd.Endpoints = append(sd.Endpoints, ed) } for _, a := range httpSvc.HTTPEndpoints { collectUserTypes(a.Body.Type, func(ut expr.UserType) { - if d := attributeTypeData(ut, true, true, true, rd); d != nil { - rd.ServerBodyAttributeTypes = append(rd.ServerBodyAttributeTypes, d) + if d := attributeTypeData(ut, true, true, true, sd); d != nil { + sd.ServerBodyAttributeTypes = append(sd.ServerBodyAttributeTypes, d) } - if d := attributeTypeData(ut, true, false, false, rd); d != nil { - rd.ClientBodyAttributeTypes = append(rd.ClientBodyAttributeTypes, d) + if d := attributeTypeData(ut, true, false, false, sd); d != nil { + sd.ClientBodyAttributeTypes = append(sd.ClientBodyAttributeTypes, d) } }) if a.MethodExpr.StreamingPayload.Type != expr.Empty { collectUserTypes(a.StreamingBody.Type, func(ut expr.UserType) { - if d := attributeTypeData(ut, true, true, true, rd); d != nil { - rd.ServerBodyAttributeTypes = append(rd.ServerBodyAttributeTypes, d) + if d := attributeTypeData(ut, true, true, true, sd); d != nil { + sd.ServerBodyAttributeTypes = append(sd.ServerBodyAttributeTypes, d) } - if d := attributeTypeData(ut, true, false, false, rd); d != nil { - rd.ClientBodyAttributeTypes = append(rd.ClientBodyAttributeTypes, d) + if d := attributeTypeData(ut, true, false, false, sd); d != nil { + sd.ClientBodyAttributeTypes = append(sd.ClientBodyAttributeTypes, d) } }) } @@ -900,8 +900,8 @@ func (ServicesData) analyze(httpSvc *expr.HTTPServiceExpr) *ServiceData { // NOTE: ServerBodyAttributeTypes for response body types are // collected in buildResponseBodyType because we have to generate // body types for each view in a result type. - if d := attributeTypeData(ut, false, true, false, rd); d != nil { - rd.ClientBodyAttributeTypes = append(rd.ClientBodyAttributeTypes, d) + if d := attributeTypeData(ut, false, true, false, sd); d != nil { + sd.ClientBodyAttributeTypes = append(sd.ClientBodyAttributeTypes, d) } }) } @@ -912,14 +912,14 @@ func (ServicesData) analyze(httpSvc *expr.HTTPServiceExpr) *ServiceData { // NOTE: ServerBodyAttributeTypes for error response body types are // collected in buildResponseBodyType because we have to generate // body types for each view in a result type. - if d := attributeTypeData(ut, false, true, false, rd); d != nil { - rd.ClientBodyAttributeTypes = append(rd.ClientBodyAttributeTypes, d) + if d := attributeTypeData(ut, false, true, false, sd); d != nil { + sd.ClientBodyAttributeTypes = append(sd.ClientBodyAttributeTypes, d) } }) } } - return rd + return sd } // makeHTTPType traverses the attribute recursively and performs these actions: @@ -2586,9 +2586,10 @@ func attributeTypeData(ut expr.UserType, req, ptr, server bool, rd *ServiceData) ctx = "response" } desc = name + " is used to define fields on " + ctx + " body types." - if req || !req && !server { - // generate validations for responses client-side and for - // requests server-side and CLI + if (req || !req && !server) && !expr.IsAlias(ut) { + // Generate validations for responses client-side and for + // requests server-side and CLI. + // Alias types are validated inline in the parent type validate = codegen.ValidationCode(ut.Attribute(), ut, hctx, true, expr.IsAlias(ut), false, "body") } if validate != "" { diff --git a/vendor/goa.design/goa/v3/http/codegen/templates/cli_end.go.tpl b/vendor/goa.design/goa/v3/http/codegen/templates/cli_end.go.tpl index f94e8b7878..31c52c9eb3 100644 --- a/vendor/goa.design/goa/v3/http/codegen/templates/cli_end.go.tpl +++ b/vendor/goa.design/goa/v3/http/codegen/templates/cli_end.go.tpl @@ -5,20 +5,25 @@ return cli.ParseEndpoint( goahttp.RequestEncoder, goahttp.ResponseDecoder, debug, - {{- if needStream .Services }} +{{- if needStream .Services }} dialer, - {{- range $svc := .Services }} - {{- if hasWebSocket $svc }} - nil, - {{- end }} - {{- end }} + {{- range $svc := .Services }} + {{- if hasWebSocket $svc }} + nil, {{- end }} - {{- range .Services }} - {{- range .Endpoints }} - {{- if .MultipartRequestDecoder }} + {{- end }} +{{- end }} +{{- range .Services }} + {{- range .Endpoints }} + {{- if .MultipartRequestDecoder }} {{ $.APIPkg }}.{{ .MultipartRequestEncoder.FuncName }}, - {{- end }} - {{- end }} {{- end }} + {{- end }} +{{- end }} +{{- range .Services }} + {{- if .Service.ClientInterceptors }} + {{ .Service.VarName }}Interceptors, + {{- end }} +{{- end }} ) -} +} \ No newline at end of file diff --git a/vendor/goa.design/goa/v3/http/codegen/templates/cli_start.go.tpl b/vendor/goa.design/goa/v3/http/codegen/templates/cli_start.go.tpl index c068dd6f7a..8ca80e51f8 100644 --- a/vendor/goa.design/goa/v3/http/codegen/templates/cli_start.go.tpl +++ b/vendor/goa.design/goa/v3/http/codegen/templates/cli_start.go.tpl @@ -1,10 +1,20 @@ func doHTTP(scheme, host string, timeout int, debug bool) (goa.Endpoint, any, error) { var ( doer goahttp.Doer +{{- range .Services }} + {{- if .Service.ClientInterceptors }} + {{ .Service.VarName }}Interceptors {{ .Service.PkgName }}.ClientInterceptors + {{- end }} +{{- end }} ) { doer = &http.Client{Timeout: time.Duration(timeout) * time.Second} if debug { doer = goahttp.NewDebugDoer(doer) } +{{- range .Services }} + {{- if .Service.ClientInterceptors }} + {{ .Service.VarName }}Interceptors = {{ $.InterceptorsPkg }}.New{{ .Service.StructName }}ClientInterceptors() + {{- end }} +{{- end }} } diff --git a/vendor/goa.design/goa/v3/http/codegen/templates/parse_endpoint.go.tpl b/vendor/goa.design/goa/v3/http/codegen/templates/parse_endpoint.go.tpl index d967bcfdcb..55ef173574 100644 --- a/vendor/goa.design/goa/v3/http/codegen/templates/parse_endpoint.go.tpl +++ b/vendor/goa.design/goa/v3/http/codegen/templates/parse_endpoint.go.tpl @@ -14,12 +14,15 @@ func ParseEndpoint( {{- end }} {{- end }} {{- end }} - {{- range $c := .Commands }} + {{- range $i, $c := .Commands }} {{- range .Subcommands }} {{- if .MultipartVarName }} {{ .MultipartVarName }} {{ $c.PkgName }}.{{ .MultipartFuncName }}, {{- end }} {{- end }} + {{- if .Interceptors }} + {{ .Interceptors.VarName }} {{ .Interceptors.PkgName }}.ClientInterceptors, + {{- end }} {{- end }} ) (goa.Endpoint, any, error) { {{ .FlagsCode }} @@ -34,11 +37,15 @@ func ParseEndpoint( case "{{ .Name }}": c := {{ .PkgName }}.NewClient(scheme, host, doer, enc, dec, restore{{ if .NeedStream }}, dialer, {{ .VarName }}Configurer{{ end }}) switch epn { - {{- $pkgName := .PkgName }}{{ range .Subcommands }} + {{- $pkgName := .PkgName }} + {{- range .Subcommands }} case "{{ .Name }}": endpoint = c.{{ .MethodVarName }}({{ if .MultipartVarName }}{{ .MultipartVarName }}{{ end }}) + {{- if .Interceptors }} + endpoint = {{ .Interceptors.PkgName }}.Wrap{{ .MethodVarName }}ClientEndpoint(endpoint, {{ .Interceptors.VarName }}) + {{- end }} {{- if .BuildFunction }} - data, err = {{ $pkgName}}.{{ .BuildFunction.Name }}({{ range .BuildFunction.ActualParams }}*{{ . }}Flag, {{ end }}) + data, err = {{ $pkgName }}.{{ .BuildFunction.Name }}({{ range .BuildFunction.ActualParams }}*{{ . }}Flag, {{ end }}) {{- else if .Conversion }} {{ .Conversion }} {{- end }} diff --git a/vendor/goa.design/goa/v3/http/codegen/templates/websocket_recv.go.tpl b/vendor/goa.design/goa/v3/http/codegen/templates/websocket_recv.go.tpl index ee9e732b72..f6c1a8067c 100644 --- a/vendor/goa.design/goa/v3/http/codegen/templates/websocket_recv.go.tpl +++ b/vendor/goa.design/goa/v3/http/codegen/templates/websocket_recv.go.tpl @@ -83,3 +83,8 @@ func (s *{{ .VarName }}) {{ .RecvName }}() ({{ .RecvTypeRef }}, error) { {{- end }} {{- end }} } + +{{ comment .RecvWithContextDesc }} +func (s *{{ .VarName }}) {{ .RecvWithContextName }}(ctx context.Context) ({{ .RecvTypeRef }}, error) { + return s.{{ .RecvName }}() +} diff --git a/vendor/goa.design/goa/v3/http/codegen/templates/websocket_send.go.tpl b/vendor/goa.design/goa/v3/http/codegen/templates/websocket_send.go.tpl index d47846bc95..11f2f02b22 100644 --- a/vendor/goa.design/goa/v3/http/codegen/templates/websocket_send.go.tpl +++ b/vendor/goa.design/goa/v3/http/codegen/templates/websocket_send.go.tpl @@ -52,3 +52,8 @@ func (s *{{ .VarName }}) {{ .SendName }}(v {{ .SendTypeRef }}) error { {{- end }} {{- end }} } + +{{ comment .SendWithContextDesc }} +func (s *{{ .VarName }}) {{ .SendWithContextName }}(ctx context.Context, v {{ .SendTypeRef }}) error { + return s.{{ .SendName }}(v) +} diff --git a/vendor/goa.design/goa/v3/http/codegen/websocket.go b/vendor/goa.design/goa/v3/http/codegen/websocket.go index 59f52f7b10..b0df17604a 100644 --- a/vendor/goa.design/goa/v3/http/codegen/websocket.go +++ b/vendor/goa.design/goa/v3/http/codegen/websocket.go @@ -32,6 +32,10 @@ type ( SendName string // SendDesc is the description for the send function. SendDesc string + // SendWithContextName is the name of the send function with context. + SendWithContextName string + // SendWithContextDesc is the description for the send function with context. + SendWithContextDesc string // SendTypeName is the fully qualified type name sent through // the stream. SendTypeName string @@ -42,6 +46,10 @@ type ( RecvName string // RecvDesc is the description for the recv function. RecvDesc string + // RecvWithContextName is the name of the receive function with context. + RecvWithContextName string + // RecvWithContextDesc is the description for the recv function with context. + RecvWithContextDesc string // RecvTypeName is the fully qualified type name received from // the stream. RecvTypeName string @@ -67,158 +75,160 @@ type ( // initWebSocketData initializes the WebSocket related data in ed. func initWebSocketData(ed *EndpointData, e *expr.HTTPEndpointExpr, sd *ServiceData) { var ( - svrSendTypeName string - svrSendTypeRef string - svrRecvTypeName string - svrRecvTypeRef string - svrSendDesc string - svrRecvDesc string - svrPayload *TypeData - cliSendDesc string - cliRecvDesc string - cliPayload *TypeData - - md = ed.Method - svc = sd.Service - svcctx = serviceContext(sd.Service.PkgName, sd.Service.Scope) + svrRecvTypeName string + svrRecvTypeRef string + svrRecvDesc string + svrRecvWithContextDesc string + svrPayload *TypeData + cliSendDesc string + cliSendWithContextDesc string + cliPayload *TypeData ) - { - svrSendTypeName = ed.Result.Name - svrSendTypeRef = ed.Result.Ref - svrSendDesc = fmt.Sprintf("%s streams instances of %q to the %q endpoint websocket connection.", md.ServerStream.SendName, svrSendTypeName, md.Name) - cliRecvDesc = fmt.Sprintf("%s reads instances of %q from the %q endpoint websocket connection.", md.ClientStream.RecvName, svrSendTypeName, md.Name) - if e.MethodExpr.Stream == expr.ClientStreamKind || e.MethodExpr.Stream == expr.BidirectionalStreamKind { - svrRecvTypeName = sd.Scope.GoFullTypeName(e.MethodExpr.StreamingPayload, svc.PkgName) - svrRecvTypeRef = sd.Scope.GoFullTypeRef(e.MethodExpr.StreamingPayload, svc.PkgName) - svrPayload = buildRequestBodyType(e.StreamingBody, e.MethodExpr.StreamingPayload, e, true, sd) - if needInit(e.MethodExpr.StreamingPayload.Type) { - makeHTTPType(e.StreamingBody) - body := e.StreamingBody.Type - // generate constructor function to transform request body, - // into the method streaming payload type - var ( - name string - desc string - serverArgs []*InitArgData - serverCode string - err error - ) - { - n := codegen.Goify(e.MethodExpr.Name, true) - p := codegen.Goify(svrPayload.Name, true) - // Raw payload object has type name prefixed with endpoint name. No need to - // prefix the type name again. - if strings.HasPrefix(p, n) { - name = fmt.Sprintf("New%s", p) - } else { - name = fmt.Sprintf("New%s%s", n, p) - } - desc = fmt.Sprintf("%s builds a %s service %s endpoint payload.", name, svc.Name, e.MethodExpr.Name) - if body != expr.Empty { - var ( - ref string - svcode string - ) - { - ref = "body" - if expr.IsObject(body) { - ref = "&body" - } - if ut, ok := body.(expr.UserType); ok { - if val := ut.Attribute().Validation; val != nil { - httpctx := httpContext("", sd.Scope, true, true) - svcode = codegen.ValidationCode(ut.Attribute(), ut, httpctx, true, expr.IsAlias(ut), false, "body") - } - } - } - serverArgs = []*InitArgData{{ - Ref: ref, - AttributeData: &AttributeData{ - Name: "payload", - VarName: "body", - TypeName: sd.Scope.GoTypeName(e.StreamingBody), - TypeRef: sd.Scope.GoTypeRef(e.StreamingBody), - Type: e.StreamingBody.Type, - Required: true, - Example: e.Body.Example(expr.Root.API.ExampleGenerator), - Validate: svcode, - }, - }} - } - if body != expr.Empty { - var helpers []*codegen.TransformFunctionData + md := ed.Method + svc := sd.Service + svcctx := serviceContext(sd.Service.PkgName, sd.Service.Scope) + svrSendTypeName := ed.Result.Name + svrSendTypeRef := ed.Result.Ref + svrSendDesc := fmt.Sprintf("%s streams instances of %q to the %q endpoint websocket connection.", md.ServerStream.SendName, svrSendTypeName, md.Name) + svrSendWithContextDesc := fmt.Sprintf("%s streams instances of %q to the %q endpoint websocket connection with context.", md.ServerStream.SendWithContextName, svrSendTypeName, md.Name) + cliRecvDesc := fmt.Sprintf("%s reads instances of %q from the %q endpoint websocket connection.", md.ClientStream.RecvName, svrSendTypeName, md.Name) + cliRecvWithContextDesc := fmt.Sprintf("%s reads instances of %q from the %q endpoint websocket connection with context.", md.ClientStream.RecvWithContextName, svrSendTypeName, md.Name) + if e.MethodExpr.Stream == expr.ClientStreamKind || e.MethodExpr.Stream == expr.BidirectionalStreamKind { + svrRecvTypeName = sd.Scope.GoFullTypeName(e.MethodExpr.StreamingPayload, svc.PkgName) + svrRecvTypeRef = sd.Scope.GoFullTypeRef(e.MethodExpr.StreamingPayload, svc.PkgName) + svrPayload = buildRequestBodyType(e.StreamingBody, e.MethodExpr.StreamingPayload, e, true, sd) + if needInit(e.MethodExpr.StreamingPayload.Type) { + makeHTTPType(e.StreamingBody) + body := e.StreamingBody.Type + // generate constructor function to transform request body, + // into the method streaming payload type + var ( + name string + desc string + serverArgs []*InitArgData + serverCode string + err error + ) + n := codegen.Goify(e.MethodExpr.Name, true) + p := codegen.Goify(svrPayload.Name, true) + // Raw payload object has type name prefixed with endpoint name. No need to + // prefix the type name again. + if strings.HasPrefix(p, n) { + name = fmt.Sprintf("New%s", p) + } else { + name = fmt.Sprintf("New%s%s", n, p) + } + desc = fmt.Sprintf("%s builds a %s service %s endpoint payload.", name, svc.Name, e.MethodExpr.Name) + if body != expr.Empty { + ref := "body" + if expr.IsObject(body) { + ref = "&body" + } + var svcode string + if ut, ok := body.(expr.UserType); ok { + if val := ut.Attribute().Validation; val != nil { httpctx := httpContext("", sd.Scope, true, true) - serverCode, helpers, err = marshal(e.StreamingBody, e.MethodExpr.StreamingPayload, "body", "v", httpctx, svcctx) - if err == nil { - sd.ServerTransformHelpers = codegen.AppendHelpers(sd.ServerTransformHelpers, helpers) - } - } - if err != nil { - fmt.Println(err.Error()) // TBD validate DSL so errors are not possible + svcode = codegen.ValidationCode(ut.Attribute(), ut, httpctx, true, expr.IsAlias(ut), false, "body") } } - svrPayload.Init = &InitData{ - Name: name, - Description: desc, - ServerArgs: serverArgs, - ReturnTypeName: svc.Scope.GoFullTypeName(e.MethodExpr.StreamingPayload, svc.PkgName), - ReturnTypeRef: svc.Scope.GoFullTypeRef(e.MethodExpr.StreamingPayload, svc.PkgName), - ReturnIsStruct: expr.IsObject(e.MethodExpr.StreamingPayload.Type), - ReturnTypePkg: svc.PkgName, - ServerCode: serverCode, + serverArgs = []*InitArgData{{ + Ref: ref, + AttributeData: &AttributeData{ + Name: "payload", + VarName: "body", + TypeName: sd.Scope.GoTypeName(e.StreamingBody), + TypeRef: sd.Scope.GoTypeRef(e.StreamingBody), + Type: e.StreamingBody.Type, + Required: true, + Example: e.Body.Example(expr.Root.API.ExampleGenerator), + Validate: svcode, + }, + }} + } + if body != expr.Empty { + var helpers []*codegen.TransformFunctionData + httpctx := httpContext("", sd.Scope, true, true) + serverCode, helpers, err = marshal(e.StreamingBody, e.MethodExpr.StreamingPayload, "body", "v", httpctx, svcctx) + if err == nil { + sd.ServerTransformHelpers = codegen.AppendHelpers(sd.ServerTransformHelpers, helpers) } } - cliPayload = buildRequestBodyType(e.StreamingBody, e.MethodExpr.StreamingPayload, e, false, sd) - if cliPayload != nil { - sd.ClientTypeNames[cliPayload.Name] = false - sd.ServerTypeNames[cliPayload.Name] = false + if err != nil { + fmt.Println(err.Error()) // TBD validate DSL so errors are not possible } - if e.MethodExpr.Stream == expr.ClientStreamKind { - svrSendDesc = fmt.Sprintf("%s streams instances of %q to the %q endpoint websocket connection and closes the connection.", md.ServerStream.SendName, svrSendTypeName, md.Name) - cliRecvDesc = fmt.Sprintf("%s stops sending messages to the %q endpoint websocket connection and reads instances of %q from the connection.", md.ClientStream.RecvName, md.Name, svrSendTypeName) + svrPayload.Init = &InitData{ + Name: name, + Description: desc, + ServerArgs: serverArgs, + ReturnTypeName: svc.Scope.GoFullTypeName(e.MethodExpr.StreamingPayload, svc.PkgName), + ReturnTypeRef: svc.Scope.GoFullTypeRef(e.MethodExpr.StreamingPayload, svc.PkgName), + ReturnIsStruct: expr.IsObject(e.MethodExpr.StreamingPayload.Type), + ReturnTypePkg: svc.PkgName, + ServerCode: serverCode, } - svrRecvDesc = fmt.Sprintf("%s reads instances of %q from the %q endpoint websocket connection.", md.ServerStream.RecvName, svrRecvTypeName, md.Name) - cliSendDesc = fmt.Sprintf("%s streams instances of %q to the %q endpoint websocket connection.", md.ClientStream.SendName, svrRecvTypeName, md.Name) } + cliPayload = buildRequestBodyType(e.StreamingBody, e.MethodExpr.StreamingPayload, e, false, sd) + if cliPayload != nil { + sd.ClientTypeNames[cliPayload.Name] = false + sd.ServerTypeNames[cliPayload.Name] = false + } + if e.MethodExpr.Stream == expr.ClientStreamKind { + svrSendDesc = fmt.Sprintf("%s streams instances of %q to the %q endpoint websocket connection and closes the connection.", md.ServerStream.SendName, svrSendTypeName, md.Name) + svrSendWithContextDesc = fmt.Sprintf("%s streams instances of %q to the %q endpoint websocket connection with context and closes the connection.", md.ServerStream.SendWithContextName, svrSendTypeName, md.Name) + cliRecvDesc = fmt.Sprintf("%s stops sending messages to the %q endpoint websocket connection and reads instances of %q from the connection.", md.ClientStream.RecvName, md.Name, svrSendTypeName) + cliRecvWithContextDesc = fmt.Sprintf("%s stops sending messages to the %q endpoint websocket connection and reads instances of %q from the connection with context.", md.ClientStream.RecvWithContextName, md.Name, svrSendTypeName) + } + svrRecvDesc = fmt.Sprintf("%s reads instances of %q from the %q endpoint websocket connection.", md.ServerStream.RecvName, svrRecvTypeName, md.Name) + svrRecvWithContextDesc = fmt.Sprintf("%s reads instances of %q from the %q endpoint websocket connection with context.", md.ServerStream.RecvWithContextName, svrRecvTypeName, md.Name) + cliSendDesc = fmt.Sprintf("%s streams instances of %q to the %q endpoint websocket connection.", md.ClientStream.SendName, svrRecvTypeName, md.Name) + cliSendWithContextDesc = fmt.Sprintf("%s streams instances of %q to the %q endpoint websocket connection with context.", md.ClientStream.SendWithContextName, svrRecvTypeName, md.Name) } ed.ServerWebSocket = &WebSocketData{ - VarName: md.ServerStream.VarName, - Interface: fmt.Sprintf("%s.%s", svc.PkgName, md.ServerStream.Interface), - Endpoint: ed, - Payload: svrPayload, - Response: ed.Result.Responses[0], - PkgName: svc.PkgName, - Type: "server", - Kind: md.ServerStream.Kind, - SendName: md.ServerStream.SendName, - SendDesc: svrSendDesc, - SendTypeName: svrSendTypeName, - SendTypeRef: svrSendTypeRef, - RecvName: md.ServerStream.RecvName, - RecvDesc: svrRecvDesc, - RecvTypeName: svrRecvTypeName, - RecvTypeRef: svrRecvTypeRef, - RecvTypeIsPointer: expr.IsArray(e.MethodExpr.StreamingPayload.Type) || expr.IsMap(e.MethodExpr.StreamingPayload.Type), - MustClose: md.ServerStream.MustClose, + VarName: md.ServerStream.VarName, + Interface: fmt.Sprintf("%s.%s", svc.PkgName, md.ServerStream.Interface), + Endpoint: ed, + Payload: svrPayload, + Response: ed.Result.Responses[0], + PkgName: svc.PkgName, + Type: "server", + Kind: md.ServerStream.Kind, + SendName: md.ServerStream.SendName, + SendDesc: svrSendDesc, + SendWithContextName: md.ServerStream.SendWithContextName, + SendWithContextDesc: svrSendWithContextDesc, + SendTypeName: svrSendTypeName, + SendTypeRef: svrSendTypeRef, + RecvName: md.ServerStream.RecvName, + RecvDesc: svrRecvDesc, + RecvWithContextName: md.ServerStream.RecvWithContextName, + RecvWithContextDesc: svrRecvWithContextDesc, + RecvTypeName: svrRecvTypeName, + RecvTypeRef: svrRecvTypeRef, + RecvTypeIsPointer: expr.IsArray(e.MethodExpr.StreamingPayload.Type) || expr.IsMap(e.MethodExpr.StreamingPayload.Type), + MustClose: md.ServerStream.MustClose, } ed.ClientWebSocket = &WebSocketData{ - VarName: md.ClientStream.VarName, - Interface: fmt.Sprintf("%s.%s", svc.PkgName, md.ClientStream.Interface), - Endpoint: ed, - Payload: cliPayload, - Response: ed.Result.Responses[0], - PkgName: svc.PkgName, - Type: "client", - Kind: md.ClientStream.Kind, - SendName: md.ClientStream.SendName, - SendDesc: cliSendDesc, - SendTypeName: svrRecvTypeName, - SendTypeRef: svrRecvTypeRef, - RecvName: md.ClientStream.RecvName, - RecvDesc: cliRecvDesc, - RecvTypeName: svrSendTypeName, - RecvTypeRef: svrSendTypeRef, - MustClose: md.ClientStream.MustClose, + VarName: md.ClientStream.VarName, + Interface: fmt.Sprintf("%s.%s", svc.PkgName, md.ClientStream.Interface), + Endpoint: ed, + Payload: cliPayload, + Response: ed.Result.Responses[0], + PkgName: svc.PkgName, + Type: "client", + Kind: md.ClientStream.Kind, + SendName: md.ClientStream.SendName, + SendDesc: cliSendDesc, + SendWithContextName: md.ClientStream.SendWithContextName, + SendWithContextDesc: cliSendWithContextDesc, + SendTypeName: svrRecvTypeName, + SendTypeRef: svrRecvTypeRef, + RecvName: md.ClientStream.RecvName, + RecvDesc: cliRecvDesc, + RecvWithContextName: md.ClientStream.RecvWithContextName, + RecvWithContextDesc: cliRecvWithContextDesc, + RecvTypeName: svrSendTypeName, + RecvTypeRef: svrSendTypeRef, + MustClose: md.ClientStream.MustClose, } } diff --git a/vendor/goa.design/goa/v3/pkg/interceptor.go b/vendor/goa.design/goa/v3/pkg/interceptor.go new file mode 100644 index 0000000000..1c3abd1313 --- /dev/null +++ b/vendor/goa.design/goa/v3/pkg/interceptor.go @@ -0,0 +1,30 @@ +package goa + +type ( + // InterceptorInfo contains information about the request shared between + // all interceptors in the service chain. It provides access to the service name, + // method name, the type of call the interceptor is handling (unary, streaming send, + // or streaming receive), and the request payload. + InterceptorInfo interface { + // Service returns the name of the service handling the request. + Service() string + // Method returns the name of the method handling the request. + Method() string + // CallType returns the type of call the interceptor is handling. + CallType() InterceptorCallType + // RawPayload returns the raw payload of the request. + RawPayload() any + } + + // InterceptorCallType is the type of call the interceptor is handling + InterceptorCallType int +) + +const ( + // InterceptorUnary indicates the interceptor is handling a unary call + InterceptorUnary InterceptorCallType = iota + // InterceptorStreamingSend indicates the interceptor is handling a streaming Send + InterceptorStreamingSend + // InterceptorStreamingRecv indicates the interceptor is handling a streaming Recv + InterceptorStreamingRecv +) diff --git a/vendor/goa.design/goa/v3/pkg/version.go b/vendor/goa.design/goa/v3/pkg/version.go index 3c8bef3112..cece3fef6b 100644 --- a/vendor/goa.design/goa/v3/pkg/version.go +++ b/vendor/goa.design/goa/v3/pkg/version.go @@ -10,9 +10,9 @@ const ( // Major version number Major = 3 // Minor version number - Minor = 19 + Minor = 20 // Build number - Build = 1 + Build = 0 // Suffix - set to empty string in release tag commits. Suffix = "" ) diff --git a/vendor/golang.org/x/net/http2/http2.go b/vendor/golang.org/x/net/http2/http2.go index c7601c909f..6c18ea230b 100644 --- a/vendor/golang.org/x/net/http2/http2.go +++ b/vendor/golang.org/x/net/http2/http2.go @@ -34,11 +34,19 @@ import ( ) var ( - VerboseLogs bool - logFrameWrites bool - logFrameReads bool - inTests bool - disableExtendedConnectProtocol bool + VerboseLogs bool + logFrameWrites bool + logFrameReads bool + inTests bool + + // Enabling extended CONNECT by causes browsers to attempt to use + // WebSockets-over-HTTP/2. This results in problems when the server's websocket + // package doesn't support extended CONNECT. + // + // Disable extended CONNECT by default for now. + // + // Issue #71128. + disableExtendedConnectProtocol = true ) func init() { @@ -51,8 +59,8 @@ func init() { logFrameWrites = true logFrameReads = true } - if strings.Contains(e, "http2xconnect=0") { - disableExtendedConnectProtocol = true + if strings.Contains(e, "http2xconnect=1") { + disableExtendedConnectProtocol = false } } @@ -407,23 +415,6 @@ func (s *sorter) SortStrings(ss []string) { s.v = save } -// validPseudoPath reports whether v is a valid :path pseudo-header -// value. It must be either: -// -// - a non-empty string starting with '/' -// - the string '*', for OPTIONS requests. -// -// For now this is only used a quick check for deciding when to clean -// up Opaque URLs before sending requests from the Transport. -// See golang.org/issue/16847 -// -// We used to enforce that the path also didn't start with "//", but -// Google's GFE accepts such paths and Chrome sends them, so ignore -// that part of the spec. See golang.org/issue/19103. -func validPseudoPath(v string) bool { - return (len(v) > 0 && v[0] == '/') || v == "*" -} - // incomparable is a zero-width, non-comparable type. Adding it to a struct // makes that struct also non-comparable, and generally doesn't add // any size (as long as it's first). diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go index b55547aec6..7434b87843 100644 --- a/vendor/golang.org/x/net/http2/server.go +++ b/vendor/golang.org/x/net/http2/server.go @@ -50,6 +50,7 @@ import ( "golang.org/x/net/http/httpguts" "golang.org/x/net/http2/hpack" + "golang.org/x/net/internal/httpcommon" ) const ( @@ -812,8 +813,7 @@ const maxCachedCanonicalHeadersKeysSize = 2048 func (sc *serverConn) canonicalHeader(v string) string { sc.serveG.check() - buildCommonHeaderMapsOnce() - cv, ok := commonCanonHeader[v] + cv, ok := httpcommon.CachedCanonicalHeader(v) if ok { return cv } diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go index b2e2ed3373..f2c166b615 100644 --- a/vendor/golang.org/x/net/http2/transport.go +++ b/vendor/golang.org/x/net/http2/transport.go @@ -25,7 +25,6 @@ import ( "net/http" "net/http/httptrace" "net/textproto" - "sort" "strconv" "strings" "sync" @@ -35,6 +34,7 @@ import ( "golang.org/x/net/http/httpguts" "golang.org/x/net/http2/hpack" "golang.org/x/net/idna" + "golang.org/x/net/internal/httpcommon" ) const ( @@ -1275,23 +1275,6 @@ func (cc *ClientConn) closeForLostPing() { // exported. At least they'll be DeepEqual for h1-vs-h2 comparisons tests. var errRequestCanceled = errors.New("net/http: request canceled") -func commaSeparatedTrailers(req *http.Request) (string, error) { - keys := make([]string, 0, len(req.Trailer)) - for k := range req.Trailer { - k = canonicalHeader(k) - switch k { - case "Transfer-Encoding", "Trailer", "Content-Length": - return "", fmt.Errorf("invalid Trailer key %q", k) - } - keys = append(keys, k) - } - if len(keys) > 0 { - sort.Strings(keys) - return strings.Join(keys, ","), nil - } - return "", nil -} - func (cc *ClientConn) responseHeaderTimeout() time.Duration { if cc.t.t1 != nil { return cc.t.t1.ResponseHeaderTimeout @@ -1303,35 +1286,6 @@ func (cc *ClientConn) responseHeaderTimeout() time.Duration { return 0 } -// checkConnHeaders checks whether req has any invalid connection-level headers. -// per RFC 7540 section 8.1.2.2: Connection-Specific Header Fields. -// Certain headers are special-cased as okay but not transmitted later. -func checkConnHeaders(req *http.Request) error { - if v := req.Header.Get("Upgrade"); v != "" { - return fmt.Errorf("http2: invalid Upgrade request header: %q", req.Header["Upgrade"]) - } - if vv := req.Header["Transfer-Encoding"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && vv[0] != "chunked") { - return fmt.Errorf("http2: invalid Transfer-Encoding request header: %q", vv) - } - if vv := req.Header["Connection"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && !asciiEqualFold(vv[0], "close") && !asciiEqualFold(vv[0], "keep-alive")) { - return fmt.Errorf("http2: invalid Connection request header: %q", vv) - } - return nil -} - -// actualContentLength returns a sanitized version of -// req.ContentLength, where 0 actually means zero (not unknown) and -1 -// means unknown. -func actualContentLength(req *http.Request) int64 { - if req.Body == nil || req.Body == http.NoBody { - return 0 - } - if req.ContentLength != 0 { - return req.ContentLength - } - return -1 -} - func (cc *ClientConn) decrStreamReservations() { cc.mu.Lock() defer cc.mu.Unlock() @@ -1356,7 +1310,7 @@ func (cc *ClientConn) roundTrip(req *http.Request, streamf func(*clientStream)) reqCancel: req.Cancel, isHead: req.Method == "HEAD", reqBody: req.Body, - reqBodyContentLength: actualContentLength(req), + reqBodyContentLength: httpcommon.ActualContentLength(req), trace: httptrace.ContextClientTrace(ctx), peerClosed: make(chan struct{}), abort: make(chan struct{}), @@ -1364,25 +1318,7 @@ func (cc *ClientConn) roundTrip(req *http.Request, streamf func(*clientStream)) donec: make(chan struct{}), } - // TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere? - if !cc.t.disableCompression() && - req.Header.Get("Accept-Encoding") == "" && - req.Header.Get("Range") == "" && - !cs.isHead { - // Request gzip only, not deflate. Deflate is ambiguous and - // not as universally supported anyway. - // See: https://zlib.net/zlib_faq.html#faq39 - // - // Note that we don't request this for HEAD requests, - // due to a bug in nginx: - // http://trac.nginx.org/nginx/ticket/358 - // https://golang.org/issue/5522 - // - // We don't request gzip if the request is for a range, since - // auto-decoding a portion of a gzipped document will just fail - // anyway. See https://golang.org/issue/8923 - cs.requestedGzip = true - } + cs.requestedGzip = httpcommon.IsRequestGzip(req, cc.t.disableCompression()) go cs.doRequest(req, streamf) @@ -1413,7 +1349,7 @@ func (cc *ClientConn) roundTrip(req *http.Request, streamf func(*clientStream)) } res.Request = req res.TLS = cc.tlsState - if res.Body == noBody && actualContentLength(req) == 0 { + if res.Body == noBody && httpcommon.ActualContentLength(req) == 0 { // If there isn't a request or response body still being // written, then wait for the stream to be closed before // RoundTrip returns. @@ -1496,10 +1432,6 @@ func (cs *clientStream) writeRequest(req *http.Request, streamf func(*clientStre cc := cs.cc ctx := cs.ctx - if err := checkConnHeaders(req); err != nil { - return err - } - // wait for setting frames to be received, a server can change this value later, // but we just wait for the first settings frame var isExtendedConnect bool @@ -1663,20 +1595,22 @@ func (cs *clientStream) encodeAndWriteHeaders(req *http.Request) error { // we send: HEADERS{1}, CONTINUATION{0,} + DATA{0,} (DATA is // sent by writeRequestBody below, along with any Trailers, // again in form HEADERS{1}, CONTINUATION{0,}) - trailers, err := commaSeparatedTrailers(req) - if err != nil { - return err - } - hasTrailers := trailers != "" - contentLen := actualContentLength(req) - hasBody := contentLen != 0 - hdrs, err := cc.encodeHeaders(req, cs.requestedGzip, trailers, contentLen) + cc.hbuf.Reset() + res, err := httpcommon.EncodeHeaders(httpcommon.EncodeHeadersParam{ + Request: req, + AddGzipHeader: cs.requestedGzip, + PeerMaxHeaderListSize: cc.peerMaxHeaderListSize, + DefaultUserAgent: defaultUserAgent, + }, func(name, value string) { + cc.writeHeader(name, value) + }) if err != nil { - return err + return fmt.Errorf("http2: %w", err) } + hdrs := cc.hbuf.Bytes() // Write the request. - endStream := !hasBody && !hasTrailers + endStream := !res.HasBody && !res.HasTrailers cs.sentHeaders = true err = cc.writeHeaders(cs.ID, endStream, int(cc.maxFrameSize), hdrs) traceWroteHeaders(cs.trace) @@ -2070,218 +2004,6 @@ func (cs *clientStream) awaitFlowControl(maxBytes int) (taken int32, err error) } } -func validateHeaders(hdrs http.Header) string { - for k, vv := range hdrs { - if !httpguts.ValidHeaderFieldName(k) && k != ":protocol" { - return fmt.Sprintf("name %q", k) - } - for _, v := range vv { - if !httpguts.ValidHeaderFieldValue(v) { - // Don't include the value in the error, - // because it may be sensitive. - return fmt.Sprintf("value for header %q", k) - } - } - } - return "" -} - -var errNilRequestURL = errors.New("http2: Request.URI is nil") - -func isNormalConnect(req *http.Request) bool { - return req.Method == "CONNECT" && req.Header.Get(":protocol") == "" -} - -// requires cc.wmu be held. -func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trailers string, contentLength int64) ([]byte, error) { - cc.hbuf.Reset() - if req.URL == nil { - return nil, errNilRequestURL - } - - host := req.Host - if host == "" { - host = req.URL.Host - } - host, err := httpguts.PunycodeHostPort(host) - if err != nil { - return nil, err - } - if !httpguts.ValidHostHeader(host) { - return nil, errors.New("http2: invalid Host header") - } - - var path string - if !isNormalConnect(req) { - path = req.URL.RequestURI() - if !validPseudoPath(path) { - orig := path - path = strings.TrimPrefix(path, req.URL.Scheme+"://"+host) - if !validPseudoPath(path) { - if req.URL.Opaque != "" { - return nil, fmt.Errorf("invalid request :path %q from URL.Opaque = %q", orig, req.URL.Opaque) - } else { - return nil, fmt.Errorf("invalid request :path %q", orig) - } - } - } - } - - // Check for any invalid headers+trailers and return an error before we - // potentially pollute our hpack state. (We want to be able to - // continue to reuse the hpack encoder for future requests) - if err := validateHeaders(req.Header); err != "" { - return nil, fmt.Errorf("invalid HTTP header %s", err) - } - if err := validateHeaders(req.Trailer); err != "" { - return nil, fmt.Errorf("invalid HTTP trailer %s", err) - } - - enumerateHeaders := func(f func(name, value string)) { - // 8.1.2.3 Request Pseudo-Header Fields - // The :path pseudo-header field includes the path and query parts of the - // target URI (the path-absolute production and optionally a '?' character - // followed by the query production, see Sections 3.3 and 3.4 of - // [RFC3986]). - f(":authority", host) - m := req.Method - if m == "" { - m = http.MethodGet - } - f(":method", m) - if !isNormalConnect(req) { - f(":path", path) - f(":scheme", req.URL.Scheme) - } - if trailers != "" { - f("trailer", trailers) - } - - var didUA bool - for k, vv := range req.Header { - if asciiEqualFold(k, "host") || asciiEqualFold(k, "content-length") { - // Host is :authority, already sent. - // Content-Length is automatic, set below. - continue - } else if asciiEqualFold(k, "connection") || - asciiEqualFold(k, "proxy-connection") || - asciiEqualFold(k, "transfer-encoding") || - asciiEqualFold(k, "upgrade") || - asciiEqualFold(k, "keep-alive") { - // Per 8.1.2.2 Connection-Specific Header - // Fields, don't send connection-specific - // fields. We have already checked if any - // are error-worthy so just ignore the rest. - continue - } else if asciiEqualFold(k, "user-agent") { - // Match Go's http1 behavior: at most one - // User-Agent. If set to nil or empty string, - // then omit it. Otherwise if not mentioned, - // include the default (below). - didUA = true - if len(vv) < 1 { - continue - } - vv = vv[:1] - if vv[0] == "" { - continue - } - } else if asciiEqualFold(k, "cookie") { - // Per 8.1.2.5 To allow for better compression efficiency, the - // Cookie header field MAY be split into separate header fields, - // each with one or more cookie-pairs. - for _, v := range vv { - for { - p := strings.IndexByte(v, ';') - if p < 0 { - break - } - f("cookie", v[:p]) - p++ - // strip space after semicolon if any. - for p+1 <= len(v) && v[p] == ' ' { - p++ - } - v = v[p:] - } - if len(v) > 0 { - f("cookie", v) - } - } - continue - } - - for _, v := range vv { - f(k, v) - } - } - if shouldSendReqContentLength(req.Method, contentLength) { - f("content-length", strconv.FormatInt(contentLength, 10)) - } - if addGzipHeader { - f("accept-encoding", "gzip") - } - if !didUA { - f("user-agent", defaultUserAgent) - } - } - - // Do a first pass over the headers counting bytes to ensure - // we don't exceed cc.peerMaxHeaderListSize. This is done as a - // separate pass before encoding the headers to prevent - // modifying the hpack state. - hlSize := uint64(0) - enumerateHeaders(func(name, value string) { - hf := hpack.HeaderField{Name: name, Value: value} - hlSize += uint64(hf.Size()) - }) - - if hlSize > cc.peerMaxHeaderListSize { - return nil, errRequestHeaderListSize - } - - trace := httptrace.ContextClientTrace(req.Context()) - traceHeaders := traceHasWroteHeaderField(trace) - - // Header list size is ok. Write the headers. - enumerateHeaders(func(name, value string) { - name, ascii := lowerHeader(name) - if !ascii { - // Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header - // field names have to be ASCII characters (just as in HTTP/1.x). - return - } - cc.writeHeader(name, value) - if traceHeaders { - traceWroteHeaderField(trace, name, value) - } - }) - - return cc.hbuf.Bytes(), nil -} - -// shouldSendReqContentLength reports whether the http2.Transport should send -// a "content-length" request header. This logic is basically a copy of the net/http -// transferWriter.shouldSendContentLength. -// The contentLength is the corrected contentLength (so 0 means actually 0, not unknown). -// -1 means unknown. -func shouldSendReqContentLength(method string, contentLength int64) bool { - if contentLength > 0 { - return true - } - if contentLength < 0 { - return false - } - // For zero bodies, whether we send a content-length depends on the method. - // It also kinda doesn't matter for http2 either way, with END_STREAM. - switch method { - case "POST", "PUT", "PATCH": - return true - default: - return false - } -} - // requires cc.wmu be held. func (cc *ClientConn) encodeTrailers(trailer http.Header) ([]byte, error) { cc.hbuf.Reset() @@ -2298,7 +2020,7 @@ func (cc *ClientConn) encodeTrailers(trailer http.Header) ([]byte, error) { } for k, vv := range trailer { - lowKey, ascii := lowerHeader(k) + lowKey, ascii := httpcommon.LowerHeader(k) if !ascii { // Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header // field names have to be ASCII characters (just as in HTTP/1.x). @@ -2653,7 +2375,7 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra Status: status + " " + http.StatusText(statusCode), } for _, hf := range regularFields { - key := canonicalHeader(hf.Name) + key := httpcommon.CanonicalHeader(hf.Name) if key == "Trailer" { t := res.Trailer if t == nil { @@ -2661,7 +2383,7 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra res.Trailer = t } foreachHeaderElement(hf.Value, func(v string) { - t[canonicalHeader(v)] = nil + t[httpcommon.CanonicalHeader(v)] = nil }) } else { vv := header[key] @@ -2785,7 +2507,7 @@ func (rl *clientConnReadLoop) processTrailers(cs *clientStream, f *MetaHeadersFr trailer := make(http.Header) for _, hf := range f.RegularFields() { - key := canonicalHeader(hf.Name) + key := httpcommon.CanonicalHeader(hf.Name) trailer[key] = append(trailer[key], hf.Value) } cs.trailer = trailer @@ -3331,7 +3053,7 @@ func (cc *ClientConn) writeStreamReset(streamID uint32, code ErrCode, ping bool, var ( errResponseHeaderListSize = errors.New("http2: response header list larger than advertised limit") - errRequestHeaderListSize = errors.New("http2: request header list larger than peer's advertised limit") + errRequestHeaderListSize = httpcommon.ErrRequestHeaderListSize ) func (cc *ClientConn) logf(format string, args ...interface{}) { @@ -3515,16 +3237,6 @@ func traceFirstResponseByte(trace *httptrace.ClientTrace) { } } -func traceHasWroteHeaderField(trace *httptrace.ClientTrace) bool { - return trace != nil && trace.WroteHeaderField != nil -} - -func traceWroteHeaderField(trace *httptrace.ClientTrace, k, v string) { - if trace != nil && trace.WroteHeaderField != nil { - trace.WroteHeaderField(k, []string{v}) - } -} - func traceGot1xxResponseFunc(trace *httptrace.ClientTrace) func(int, textproto.MIMEHeader) error { if trace != nil { return trace.Got1xxResponse diff --git a/vendor/golang.org/x/net/http2/write.go b/vendor/golang.org/x/net/http2/write.go index 6ff6bee7e9..fdb35b9477 100644 --- a/vendor/golang.org/x/net/http2/write.go +++ b/vendor/golang.org/x/net/http2/write.go @@ -13,6 +13,7 @@ import ( "golang.org/x/net/http/httpguts" "golang.org/x/net/http2/hpack" + "golang.org/x/net/internal/httpcommon" ) // writeFramer is implemented by any type that is used to write frames. @@ -351,7 +352,7 @@ func encodeHeaders(enc *hpack.Encoder, h http.Header, keys []string) { } for _, k := range keys { vv := h[k] - k, ascii := lowerHeader(k) + k, ascii := httpcommon.LowerHeader(k) if !ascii { // Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header // field names have to be ASCII characters (just as in HTTP/1.x). diff --git a/vendor/golang.org/x/net/internal/httpcommon/ascii.go b/vendor/golang.org/x/net/internal/httpcommon/ascii.go new file mode 100644 index 0000000000..ed14da5afc --- /dev/null +++ b/vendor/golang.org/x/net/internal/httpcommon/ascii.go @@ -0,0 +1,53 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package httpcommon + +import "strings" + +// The HTTP protocols are defined in terms of ASCII, not Unicode. This file +// contains helper functions which may use Unicode-aware functions which would +// otherwise be unsafe and could introduce vulnerabilities if used improperly. + +// asciiEqualFold is strings.EqualFold, ASCII only. It reports whether s and t +// are equal, ASCII-case-insensitively. +func asciiEqualFold(s, t string) bool { + if len(s) != len(t) { + return false + } + for i := 0; i < len(s); i++ { + if lower(s[i]) != lower(t[i]) { + return false + } + } + return true +} + +// lower returns the ASCII lowercase version of b. +func lower(b byte) byte { + if 'A' <= b && b <= 'Z' { + return b + ('a' - 'A') + } + return b +} + +// isASCIIPrint returns whether s is ASCII and printable according to +// https://tools.ietf.org/html/rfc20#section-4.2. +func isASCIIPrint(s string) bool { + for i := 0; i < len(s); i++ { + if s[i] < ' ' || s[i] > '~' { + return false + } + } + return true +} + +// asciiToLower returns the lowercase version of s if s is ASCII and printable, +// and whether or not it was. +func asciiToLower(s string) (lower string, ok bool) { + if !isASCIIPrint(s) { + return "", false + } + return strings.ToLower(s), true +} diff --git a/vendor/golang.org/x/net/http2/headermap.go b/vendor/golang.org/x/net/internal/httpcommon/headermap.go similarity index 77% rename from vendor/golang.org/x/net/http2/headermap.go rename to vendor/golang.org/x/net/internal/httpcommon/headermap.go index 149b3dd20e..ad3fbacd60 100644 --- a/vendor/golang.org/x/net/http2/headermap.go +++ b/vendor/golang.org/x/net/internal/httpcommon/headermap.go @@ -1,8 +1,8 @@ -// Copyright 2014 The Go Authors. All rights reserved. +// Copyright 2025 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package http2 +package httpcommon import ( "net/http" @@ -88,7 +88,9 @@ func buildCommonHeaderMaps() { } } -func lowerHeader(v string) (lower string, ascii bool) { +// LowerHeader returns the lowercase form of a header name, +// used on the wire for HTTP/2 and HTTP/3 requests. +func LowerHeader(v string) (lower string, ascii bool) { buildCommonHeaderMapsOnce() if s, ok := commonLowerHeader[v]; ok { return s, true @@ -96,10 +98,18 @@ func lowerHeader(v string) (lower string, ascii bool) { return asciiToLower(v) } -func canonicalHeader(v string) string { +// CanonicalHeader canonicalizes a header name. (For example, "host" becomes "Host".) +func CanonicalHeader(v string) string { buildCommonHeaderMapsOnce() if s, ok := commonCanonHeader[v]; ok { return s } return http.CanonicalHeaderKey(v) } + +// CachedCanonicalHeader returns the canonical form of a well-known header name. +func CachedCanonicalHeader(v string) (string, bool) { + buildCommonHeaderMapsOnce() + s, ok := commonCanonHeader[v] + return s, ok +} diff --git a/vendor/golang.org/x/net/internal/httpcommon/request.go b/vendor/golang.org/x/net/internal/httpcommon/request.go new file mode 100644 index 0000000000..3439147738 --- /dev/null +++ b/vendor/golang.org/x/net/internal/httpcommon/request.go @@ -0,0 +1,379 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package httpcommon + +import ( + "errors" + "fmt" + "net/http" + "net/http/httptrace" + "sort" + "strconv" + "strings" + + "golang.org/x/net/http/httpguts" + "golang.org/x/net/http2/hpack" +) + +var ( + ErrRequestHeaderListSize = errors.New("request header list larger than peer's advertised limit") +) + +// EncodeHeadersParam is parameters to EncodeHeaders. +type EncodeHeadersParam struct { + Request *http.Request + + // AddGzipHeader indicates that an "accept-encoding: gzip" header should be + // added to the request. + AddGzipHeader bool + + // PeerMaxHeaderListSize, when non-zero, is the peer's MAX_HEADER_LIST_SIZE setting. + PeerMaxHeaderListSize uint64 + + // DefaultUserAgent is the User-Agent header to send when the request + // neither contains a User-Agent nor disables it. + DefaultUserAgent string +} + +// EncodeHeadersParam is the result of EncodeHeaders. +type EncodeHeadersResult struct { + HasBody bool + HasTrailers bool +} + +// EncodeHeaders constructs request headers common to HTTP/2 and HTTP/3. +// It validates a request and calls headerf with each pseudo-header and header +// for the request. +// The headerf function is called with the validated, canonicalized header name. +func EncodeHeaders(param EncodeHeadersParam, headerf func(name, value string)) (res EncodeHeadersResult, _ error) { + req := param.Request + + // Check for invalid connection-level headers. + if err := checkConnHeaders(req); err != nil { + return res, err + } + + if req.URL == nil { + return res, errors.New("Request.URL is nil") + } + + host := req.Host + if host == "" { + host = req.URL.Host + } + host, err := httpguts.PunycodeHostPort(host) + if err != nil { + return res, err + } + if !httpguts.ValidHostHeader(host) { + return res, errors.New("invalid Host header") + } + + // isNormalConnect is true if this is a non-extended CONNECT request. + isNormalConnect := false + protocol := req.Header.Get(":protocol") + if req.Method == "CONNECT" && protocol == "" { + isNormalConnect = true + } else if protocol != "" && req.Method != "CONNECT" { + return res, errors.New("invalid :protocol header in non-CONNECT request") + } + + // Validate the path, except for non-extended CONNECT requests which have no path. + var path string + if !isNormalConnect { + path = req.URL.RequestURI() + if !validPseudoPath(path) { + orig := path + path = strings.TrimPrefix(path, req.URL.Scheme+"://"+host) + if !validPseudoPath(path) { + if req.URL.Opaque != "" { + return res, fmt.Errorf("invalid request :path %q from URL.Opaque = %q", orig, req.URL.Opaque) + } else { + return res, fmt.Errorf("invalid request :path %q", orig) + } + } + } + } + + // Check for any invalid headers+trailers and return an error before we + // potentially pollute our hpack state. (We want to be able to + // continue to reuse the hpack encoder for future requests) + if err := validateHeaders(req.Header); err != "" { + return res, fmt.Errorf("invalid HTTP header %s", err) + } + if err := validateHeaders(req.Trailer); err != "" { + return res, fmt.Errorf("invalid HTTP trailer %s", err) + } + + contentLength := ActualContentLength(req) + + trailers, err := commaSeparatedTrailers(req) + if err != nil { + return res, err + } + + enumerateHeaders := func(f func(name, value string)) { + // 8.1.2.3 Request Pseudo-Header Fields + // The :path pseudo-header field includes the path and query parts of the + // target URI (the path-absolute production and optionally a '?' character + // followed by the query production, see Sections 3.3 and 3.4 of + // [RFC3986]). + f(":authority", host) + m := req.Method + if m == "" { + m = http.MethodGet + } + f(":method", m) + if !isNormalConnect { + f(":path", path) + f(":scheme", req.URL.Scheme) + } + if protocol != "" { + f(":protocol", protocol) + } + if trailers != "" { + f("trailer", trailers) + } + + var didUA bool + for k, vv := range req.Header { + if asciiEqualFold(k, "host") || asciiEqualFold(k, "content-length") { + // Host is :authority, already sent. + // Content-Length is automatic, set below. + continue + } else if asciiEqualFold(k, "connection") || + asciiEqualFold(k, "proxy-connection") || + asciiEqualFold(k, "transfer-encoding") || + asciiEqualFold(k, "upgrade") || + asciiEqualFold(k, "keep-alive") { + // Per 8.1.2.2 Connection-Specific Header + // Fields, don't send connection-specific + // fields. We have already checked if any + // are error-worthy so just ignore the rest. + continue + } else if asciiEqualFold(k, "user-agent") { + // Match Go's http1 behavior: at most one + // User-Agent. If set to nil or empty string, + // then omit it. Otherwise if not mentioned, + // include the default (below). + didUA = true + if len(vv) < 1 { + continue + } + vv = vv[:1] + if vv[0] == "" { + continue + } + } else if asciiEqualFold(k, "cookie") { + // Per 8.1.2.5 To allow for better compression efficiency, the + // Cookie header field MAY be split into separate header fields, + // each with one or more cookie-pairs. + for _, v := range vv { + for { + p := strings.IndexByte(v, ';') + if p < 0 { + break + } + f("cookie", v[:p]) + p++ + // strip space after semicolon if any. + for p+1 <= len(v) && v[p] == ' ' { + p++ + } + v = v[p:] + } + if len(v) > 0 { + f("cookie", v) + } + } + continue + } else if k == ":protocol" { + // :protocol pseudo-header was already sent above. + continue + } + + for _, v := range vv { + f(k, v) + } + } + if shouldSendReqContentLength(req.Method, contentLength) { + f("content-length", strconv.FormatInt(contentLength, 10)) + } + if param.AddGzipHeader { + f("accept-encoding", "gzip") + } + if !didUA { + f("user-agent", param.DefaultUserAgent) + } + } + + // Do a first pass over the headers counting bytes to ensure + // we don't exceed cc.peerMaxHeaderListSize. This is done as a + // separate pass before encoding the headers to prevent + // modifying the hpack state. + if param.PeerMaxHeaderListSize > 0 { + hlSize := uint64(0) + enumerateHeaders(func(name, value string) { + hf := hpack.HeaderField{Name: name, Value: value} + hlSize += uint64(hf.Size()) + }) + + if hlSize > param.PeerMaxHeaderListSize { + return res, ErrRequestHeaderListSize + } + } + + trace := httptrace.ContextClientTrace(req.Context()) + + // Header list size is ok. Write the headers. + enumerateHeaders(func(name, value string) { + name, ascii := LowerHeader(name) + if !ascii { + // Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header + // field names have to be ASCII characters (just as in HTTP/1.x). + return + } + + headerf(name, value) + + if trace != nil && trace.WroteHeaderField != nil { + trace.WroteHeaderField(name, []string{value}) + } + }) + + res.HasBody = contentLength != 0 + res.HasTrailers = trailers != "" + return res, nil +} + +// IsRequestGzip reports whether we should add an Accept-Encoding: gzip header +// for a request. +func IsRequestGzip(req *http.Request, disableCompression bool) bool { + // TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere? + if !disableCompression && + req.Header.Get("Accept-Encoding") == "" && + req.Header.Get("Range") == "" && + req.Method != "HEAD" { + // Request gzip only, not deflate. Deflate is ambiguous and + // not as universally supported anyway. + // See: https://zlib.net/zlib_faq.html#faq39 + // + // Note that we don't request this for HEAD requests, + // due to a bug in nginx: + // http://trac.nginx.org/nginx/ticket/358 + // https://golang.org/issue/5522 + // + // We don't request gzip if the request is for a range, since + // auto-decoding a portion of a gzipped document will just fail + // anyway. See https://golang.org/issue/8923 + return true + } + return false +} + +// checkConnHeaders checks whether req has any invalid connection-level headers. +// +// https://www.rfc-editor.org/rfc/rfc9114.html#section-4.2-3 +// https://www.rfc-editor.org/rfc/rfc9113.html#section-8.2.2-1 +// +// Certain headers are special-cased as okay but not transmitted later. +// For example, we allow "Transfer-Encoding: chunked", but drop the header when encoding. +func checkConnHeaders(req *http.Request) error { + if v := req.Header.Get("Upgrade"); v != "" { + return fmt.Errorf("invalid Upgrade request header: %q", req.Header["Upgrade"]) + } + if vv := req.Header["Transfer-Encoding"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && vv[0] != "chunked") { + return fmt.Errorf("invalid Transfer-Encoding request header: %q", vv) + } + if vv := req.Header["Connection"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && !asciiEqualFold(vv[0], "close") && !asciiEqualFold(vv[0], "keep-alive")) { + return fmt.Errorf("invalid Connection request header: %q", vv) + } + return nil +} + +func commaSeparatedTrailers(req *http.Request) (string, error) { + keys := make([]string, 0, len(req.Trailer)) + for k := range req.Trailer { + k = CanonicalHeader(k) + switch k { + case "Transfer-Encoding", "Trailer", "Content-Length": + return "", fmt.Errorf("invalid Trailer key %q", k) + } + keys = append(keys, k) + } + if len(keys) > 0 { + sort.Strings(keys) + return strings.Join(keys, ","), nil + } + return "", nil +} + +// ActualContentLength returns a sanitized version of +// req.ContentLength, where 0 actually means zero (not unknown) and -1 +// means unknown. +func ActualContentLength(req *http.Request) int64 { + if req.Body == nil || req.Body == http.NoBody { + return 0 + } + if req.ContentLength != 0 { + return req.ContentLength + } + return -1 +} + +// validPseudoPath reports whether v is a valid :path pseudo-header +// value. It must be either: +// +// - a non-empty string starting with '/' +// - the string '*', for OPTIONS requests. +// +// For now this is only used a quick check for deciding when to clean +// up Opaque URLs before sending requests from the Transport. +// See golang.org/issue/16847 +// +// We used to enforce that the path also didn't start with "//", but +// Google's GFE accepts such paths and Chrome sends them, so ignore +// that part of the spec. See golang.org/issue/19103. +func validPseudoPath(v string) bool { + return (len(v) > 0 && v[0] == '/') || v == "*" +} + +func validateHeaders(hdrs http.Header) string { + for k, vv := range hdrs { + if !httpguts.ValidHeaderFieldName(k) && k != ":protocol" { + return fmt.Sprintf("name %q", k) + } + for _, v := range vv { + if !httpguts.ValidHeaderFieldValue(v) { + // Don't include the value in the error, + // because it may be sensitive. + return fmt.Sprintf("value for header %q", k) + } + } + } + return "" +} + +// shouldSendReqContentLength reports whether we should send +// a "content-length" request header. This logic is basically a copy of the net/http +// transferWriter.shouldSendContentLength. +// The contentLength is the corrected contentLength (so 0 means actually 0, not unknown). +// -1 means unknown. +func shouldSendReqContentLength(method string, contentLength int64) bool { + if contentLength > 0 { + return true + } + if contentLength < 0 { + return false + } + // For zero bodies, whether we send a content-length depends on the method. + // It also kinda doesn't matter for http2 either way, with END_STREAM. + switch method { + case "POST", "PUT", "PATCH": + return true + default: + return false + } +} diff --git a/vendor/golang.org/x/tools/go/ast/astutil/imports.go b/vendor/golang.org/x/tools/go/ast/astutil/imports.go index 18d1adb05d..a6b5ed0a89 100644 --- a/vendor/golang.org/x/tools/go/ast/astutil/imports.go +++ b/vendor/golang.org/x/tools/go/ast/astutil/imports.go @@ -344,7 +344,12 @@ func RewriteImport(fset *token.FileSet, f *ast.File, oldPath, newPath string) (r } // UsesImport reports whether a given import is used. +// The provided File must have been parsed with syntactic object resolution +// (not using go/parser.SkipObjectResolution). func UsesImport(f *ast.File, path string) (used bool) { + if f.Scope == nil { + panic("file f was not parsed with syntactic object resolution") + } spec := importSpec(f, path) if spec == nil { return diff --git a/vendor/golang.org/x/tools/go/ast/astutil/util.go b/vendor/golang.org/x/tools/go/ast/astutil/util.go index 6bdcf70ac2..ca71e3e105 100644 --- a/vendor/golang.org/x/tools/go/ast/astutil/util.go +++ b/vendor/golang.org/x/tools/go/ast/astutil/util.go @@ -7,13 +7,5 @@ package astutil import "go/ast" // Unparen returns e with any enclosing parentheses stripped. -// TODO(adonovan): use go1.22's ast.Unparen. -func Unparen(e ast.Expr) ast.Expr { - for { - p, ok := e.(*ast.ParenExpr) - if !ok { - return e - } - e = p.X - } -} +// Deprecated: use [ast.Unparen]. +func Unparen(e ast.Expr) ast.Expr { return ast.Unparen(e) } diff --git a/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go b/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go index 137cc8df1d..65fe2628e9 100644 --- a/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go +++ b/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go @@ -2,22 +2,64 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package gcexportdata provides functions for locating, reading, and -// writing export data files containing type information produced by the -// gc compiler. This package supports go1.7 export data format and all -// later versions. -// -// Although it might seem convenient for this package to live alongside -// go/types in the standard library, this would cause version skew -// problems for developer tools that use it, since they must be able to -// consume the outputs of the gc compiler both before and after a Go -// update such as from Go 1.7 to Go 1.8. Because this package lives in -// golang.org/x/tools, sites can update their version of this repo some -// time before the Go 1.8 release and rebuild and redeploy their -// developer tools, which will then be able to consume both Go 1.7 and -// Go 1.8 export data files, so they will work before and after the -// Go update. (See discussion at https://golang.org/issue/15651.) -package gcexportdata // import "golang.org/x/tools/go/gcexportdata" +// Package gcexportdata provides functions for reading and writing +// export data, which is a serialized description of the API of a Go +// package including the names, kinds, types, and locations of all +// exported declarations. +// +// The standard Go compiler (cmd/compile) writes an export data file +// for each package it compiles, which it later reads when compiling +// packages that import the earlier one. The compiler must thus +// contain logic to both write and read export data. +// (See the "Export" section in the cmd/compile/README file.) +// +// The [Read] function in this package can read files produced by the +// compiler, producing [go/types] data structures. As a matter of +// policy, Read supports export data files produced by only the last +// two Go releases plus tip; see https://go.dev/issue/68898. The +// export data files produced by the compiler contain additional +// details related to generics, inlining, and other optimizations that +// cannot be decoded by the [Read] function. +// +// In files written by the compiler, the export data is not at the +// start of the file. Before calling Read, use [NewReader] to locate +// the desired portion of the file. +// +// The [Write] function in this package encodes the exported API of a +// Go package ([types.Package]) as a file. Such files can be later +// decoded by Read, but cannot be consumed by the compiler. +// +// # Future changes +// +// Although Read supports the formats written by both Write and the +// compiler, the two are quite different, and there is an open +// proposal (https://go.dev/issue/69491) to separate these APIs. +// +// Under that proposal, this package would ultimately provide only the +// Read operation for compiler export data, which must be defined in +// this module (golang.org/x/tools), not in the standard library, to +// avoid version skew for developer tools that need to read compiler +// export data both before and after a Go release, such as from Go +// 1.23 to Go 1.24. Because this package lives in the tools module, +// clients can update their version of the module some time before the +// Go 1.24 release and rebuild and redeploy their tools, which will +// then be able to consume both Go 1.23 and Go 1.24 export data files, +// so they will work before and after the Go update. (See discussion +// at https://go.dev/issue/15651.) +// +// The operations to import and export [go/types] data structures +// would be defined in the go/types package as Import and Export. +// [Write] would (eventually) delegate to Export, +// and [Read], when it detects a file produced by Export, +// would delegate to Import. +// +// # Deprecations +// +// The [NewImporter] and [Find] functions are deprecated and should +// not be used in new code. The [WriteBundle] and [ReadBundle] +// functions are experimental, and there is an open proposal to +// deprecate them (https://go.dev/issue/69573). +package gcexportdata import ( "bufio" @@ -64,24 +106,18 @@ func Find(importPath, srcDir string) (filename, path string) { // additional trailing data beyond the end of the export data. func NewReader(r io.Reader) (io.Reader, error) { buf := bufio.NewReader(r) - _, size, err := gcimporter.FindExportData(buf) + size, err := gcimporter.FindExportData(buf) if err != nil { return nil, err } - if size >= 0 { - // We were given an archive and found the __.PKGDEF in it. - // This tells us the size of the export data, and we don't - // need to return the entire file. - return &io.LimitedReader{ - R: buf, - N: size, - }, nil - } else { - // We were given an object file. As such, we don't know how large - // the export data is and must return the entire file. - return buf, nil - } + // We were given an archive and found the __.PKGDEF in it. + // This tells us the size of the export data, and we don't + // need to return the entire file. + return &io.LimitedReader{ + R: buf, + N: size, + }, nil } // readAll works the same way as io.ReadAll, but avoids allocations and copies @@ -100,6 +136,11 @@ func readAll(r io.Reader) ([]byte, error) { // Read reads export data from in, decodes it, and returns type // information for the package. // +// Read is capable of reading export data produced by [Write] at the +// same source code version, or by the last two Go releases (plus tip) +// of the standard Go compiler. Reading files from older compilers may +// produce an error. +// // The package path (effectively its linker symbol prefix) is // specified by path, since unlike the package name, this information // may not be recorded in the export data. @@ -128,14 +169,26 @@ func Read(in io.Reader, fset *token.FileSet, imports map[string]*types.Package, // (from "version"). Select appropriate importer. if len(data) > 0 { switch data[0] { - case 'v', 'c', 'd': // binary, till go1.10 + case 'v', 'c', 'd': + // binary, produced by cmd/compile till go1.10 return nil, fmt.Errorf("binary (%c) import format is no longer supported", data[0]) - case 'i': // indexed, till go1.19 + case 'i': + // indexed, produced by cmd/compile till go1.19, + // and also by [Write]. + // + // If proposal #69491 is accepted, go/types + // serialization will be implemented by + // types.Export, to which Write would eventually + // delegate (explicitly dropping any pretence at + // inter-version Write-Read compatibility). + // This [Read] function would delegate to types.Import + // when it detects that the file was produced by Export. _, pkg, err := gcimporter.IImportData(fset, imports, data[1:], path) return pkg, err - case 'u': // unified, from go1.20 + case 'u': + // unified, produced by cmd/compile since go1.20 _, pkg, err := gcimporter.UImportData(fset, imports, data[1:], path) return pkg, err diff --git a/vendor/golang.org/x/tools/go/packages/doc.go b/vendor/golang.org/x/tools/go/packages/doc.go index 3531ac8f5f..f1931d10ee 100644 --- a/vendor/golang.org/x/tools/go/packages/doc.go +++ b/vendor/golang.org/x/tools/go/packages/doc.go @@ -64,7 +64,7 @@ graph using the Imports fields. The Load function can be configured by passing a pointer to a Config as the first argument. A nil Config is equivalent to the zero Config, which -causes Load to run in LoadFiles mode, collecting minimal information. +causes Load to run in [LoadFiles] mode, collecting minimal information. See the documentation for type Config for details. As noted earlier, the Config.Mode controls the amount of detail @@ -72,14 +72,14 @@ reported about the loaded packages. See the documentation for type LoadMode for details. Most tools should pass their command-line arguments (after any flags) -uninterpreted to [Load], so that it can interpret them +uninterpreted to Load, so that it can interpret them according to the conventions of the underlying build system. See the Example function for typical usage. # The driver protocol -[Load] may be used to load Go packages even in Go projects that use +Load may be used to load Go packages even in Go projects that use alternative build systems, by installing an appropriate "driver" program for the build system and specifying its location in the GOPACKAGESDRIVER environment variable. @@ -97,6 +97,15 @@ JSON-encoded [DriverRequest] message providing additional information is written to the driver's standard input. The driver must write a JSON-encoded [DriverResponse] message to its standard output. (This message differs from the JSON schema produced by 'go list'.) + +The value of the PWD environment variable seen by the driver process +is the preferred name of its working directory. (The working directory +may have other aliases due to symbolic links; see the comment on the +Dir field of [exec.Cmd] for related information.) +When the driver process emits in its response the name of a file +that is a descendant of this directory, it must use an absolute path +that has the value of PWD as a prefix, to ensure that the returned +filenames satisfy the original query. */ package packages // import "golang.org/x/tools/go/packages" diff --git a/vendor/golang.org/x/tools/go/packages/external.go b/vendor/golang.org/x/tools/go/packages/external.go index 8f7afcb5df..91bd62e83b 100644 --- a/vendor/golang.org/x/tools/go/packages/external.go +++ b/vendor/golang.org/x/tools/go/packages/external.go @@ -13,6 +13,7 @@ import ( "fmt" "os" "os/exec" + "slices" "strings" ) @@ -79,7 +80,7 @@ type DriverResponse struct { // driver is the type for functions that query the build system for the // packages named by the patterns. -type driver func(cfg *Config, patterns ...string) (*DriverResponse, error) +type driver func(cfg *Config, patterns []string) (*DriverResponse, error) // findExternalDriver returns the file path of a tool that supplies // the build system package structure, or "" if not found. @@ -103,7 +104,7 @@ func findExternalDriver(cfg *Config) driver { return nil } } - return func(cfg *Config, words ...string) (*DriverResponse, error) { + return func(cfg *Config, patterns []string) (*DriverResponse, error) { req, err := json.Marshal(DriverRequest{ Mode: cfg.Mode, Env: cfg.Env, @@ -117,7 +118,7 @@ func findExternalDriver(cfg *Config) driver { buf := new(bytes.Buffer) stderr := new(bytes.Buffer) - cmd := exec.CommandContext(cfg.Context, tool, words...) + cmd := exec.CommandContext(cfg.Context, tool, patterns...) cmd.Dir = cfg.Dir // The cwd gets resolved to the real path. On Darwin, where // /tmp is a symlink, this breaks anything that expects the @@ -131,7 +132,7 @@ func findExternalDriver(cfg *Config) driver { // command. // // (See similar trick in Invocation.run in ../../internal/gocommand/invoke.go) - cmd.Env = append(slicesClip(cfg.Env), "PWD="+cfg.Dir) + cmd.Env = append(slices.Clip(cfg.Env), "PWD="+cfg.Dir) cmd.Stdin = bytes.NewReader(req) cmd.Stdout = buf cmd.Stderr = stderr @@ -150,7 +151,3 @@ func findExternalDriver(cfg *Config) driver { return &response, nil } } - -// slicesClip removes unused capacity from the slice, returning s[:len(s):len(s)]. -// TODO(adonovan): use go1.21 slices.Clip. -func slicesClip[S ~[]E, E any](s S) S { return s[:len(s):len(s)] } diff --git a/vendor/golang.org/x/tools/go/packages/golist.go b/vendor/golang.org/x/tools/go/packages/golist.go index 1a3a5b44f5..0458b4f9c4 100644 --- a/vendor/golang.org/x/tools/go/packages/golist.go +++ b/vendor/golang.org/x/tools/go/packages/golist.go @@ -80,6 +80,12 @@ type golistState struct { cfg *Config ctx context.Context + runner *gocommand.Runner + + // overlay is the JSON file that encodes the Config.Overlay + // mapping, used by 'go list -overlay=...'. + overlay string + envOnce sync.Once goEnvError error goEnv map[string]string @@ -127,7 +133,10 @@ func (state *golistState) mustGetEnv() map[string]string { // goListDriver uses the go list command to interpret the patterns and produce // the build system package structure. // See driver for more details. -func goListDriver(cfg *Config, patterns ...string) (_ *DriverResponse, err error) { +// +// overlay is the JSON file that encodes the cfg.Overlay +// mapping, used by 'go list -overlay=...' +func goListDriver(cfg *Config, runner *gocommand.Runner, overlay string, patterns []string) (_ *DriverResponse, err error) { // Make sure that any asynchronous go commands are killed when we return. parentCtx := cfg.Context if parentCtx == nil { @@ -142,13 +151,15 @@ func goListDriver(cfg *Config, patterns ...string) (_ *DriverResponse, err error cfg: cfg, ctx: ctx, vendorDirs: map[string]bool{}, + overlay: overlay, + runner: runner, } // Fill in response.Sizes asynchronously if necessary. - if cfg.Mode&NeedTypesSizes != 0 || cfg.Mode&NeedTypes != 0 { + if cfg.Mode&NeedTypesSizes != 0 || cfg.Mode&(NeedTypes|NeedTypesInfo) != 0 { errCh := make(chan error) go func() { - compiler, arch, err := getSizesForArgs(ctx, state.cfgInvocation(), cfg.gocmdRunner) + compiler, arch, err := getSizesForArgs(ctx, state.cfgInvocation(), runner) response.dr.Compiler = compiler response.dr.Arch = arch errCh <- err @@ -311,6 +322,7 @@ type jsonPackage struct { ImportPath string Dir string Name string + Target string Export string GoFiles []string CompiledGoFiles []string @@ -494,13 +506,15 @@ func (state *golistState) createDriverResponse(words ...string) (*DriverResponse pkg := &Package{ Name: p.Name, ID: p.ImportPath, + Dir: p.Dir, + Target: p.Target, GoFiles: absJoin(p.Dir, p.GoFiles, p.CgoFiles), CompiledGoFiles: absJoin(p.Dir, p.CompiledGoFiles), OtherFiles: absJoin(p.Dir, otherFiles(p)...), EmbedFiles: absJoin(p.Dir, p.EmbedFiles), EmbedPatterns: absJoin(p.Dir, p.EmbedPatterns), IgnoredFiles: absJoin(p.Dir, p.IgnoredGoFiles, p.IgnoredOtherFiles), - forTest: p.ForTest, + ForTest: p.ForTest, depsErrors: p.DepsErrors, Module: p.Module, } @@ -681,7 +695,7 @@ func (state *golistState) shouldAddFilenameFromError(p *jsonPackage) bool { // getGoVersion returns the effective minor version of the go command. func (state *golistState) getGoVersion() (int, error) { state.goVersionOnce.Do(func() { - state.goVersion, state.goVersionError = gocommand.GoVersion(state.ctx, state.cfgInvocation(), state.cfg.gocmdRunner) + state.goVersion, state.goVersionError = gocommand.GoVersion(state.ctx, state.cfgInvocation(), state.runner) }) return state.goVersion, state.goVersionError } @@ -751,7 +765,7 @@ func jsonFlag(cfg *Config, goVersion int) string { } } addFields("Name", "ImportPath", "Error") // These fields are always needed - if cfg.Mode&NeedFiles != 0 || cfg.Mode&NeedTypes != 0 { + if cfg.Mode&NeedFiles != 0 || cfg.Mode&(NeedTypes|NeedTypesInfo) != 0 { addFields("Dir", "GoFiles", "IgnoredGoFiles", "IgnoredOtherFiles", "CFiles", "CgoFiles", "CXXFiles", "MFiles", "HFiles", "FFiles", "SFiles", "SwigFiles", "SwigCXXFiles", "SysoFiles") @@ -759,7 +773,7 @@ func jsonFlag(cfg *Config, goVersion int) string { addFields("TestGoFiles", "XTestGoFiles") } } - if cfg.Mode&NeedTypes != 0 { + if cfg.Mode&(NeedTypes|NeedTypesInfo) != 0 { // CompiledGoFiles seems to be required for the test case TestCgoNoSyntax, // even when -compiled isn't passed in. // TODO(#52435): Should we make the test ask for -compiled, or automatically @@ -784,7 +798,7 @@ func jsonFlag(cfg *Config, goVersion int) string { // Request Dir in the unlikely case Export is not absolute. addFields("Dir", "Export") } - if cfg.Mode&needInternalForTest != 0 { + if cfg.Mode&NeedForTest != 0 { addFields("ForTest") } if cfg.Mode&needInternalDepsErrors != 0 { @@ -799,6 +813,9 @@ func jsonFlag(cfg *Config, goVersion int) string { if cfg.Mode&NeedEmbedPatterns != 0 { addFields("EmbedPatterns") } + if cfg.Mode&NeedTarget != 0 { + addFields("Target") + } return "-json=" + strings.Join(fields, ",") } @@ -840,7 +857,7 @@ func (state *golistState) cfgInvocation() gocommand.Invocation { Env: cfg.Env, Logf: cfg.Logf, WorkingDir: cfg.Dir, - Overlay: cfg.goListOverlayFile, + Overlay: state.overlay, } } @@ -851,11 +868,8 @@ func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer, inv := state.cfgInvocation() inv.Verb = verb inv.Args = args - gocmdRunner := cfg.gocmdRunner - if gocmdRunner == nil { - gocmdRunner = &gocommand.Runner{} - } - stdout, stderr, friendlyErr, err := gocmdRunner.RunRaw(cfg.Context, inv) + + stdout, stderr, friendlyErr, err := state.runner.RunRaw(cfg.Context, inv) if err != nil { // Check for 'go' executable not being found. if ee, ok := err.(*exec.Error); ok && ee.Err == exec.ErrNotFound { @@ -879,6 +893,12 @@ func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer, return nil, friendlyErr } + // Return an error if 'go list' failed due to missing tools in + // $GOROOT/pkg/tool/$GOOS_$GOARCH (#69606). + if len(stderr.String()) > 0 && strings.Contains(stderr.String(), `go: no such tool`) { + return nil, friendlyErr + } + // Is there an error running the C compiler in cgo? This will be reported in the "Error" field // and should be suppressed by go list -e. // diff --git a/vendor/golang.org/x/tools/go/packages/loadmode_string.go b/vendor/golang.org/x/tools/go/packages/loadmode_string.go index 5c080d21b5..69eec9f44d 100644 --- a/vendor/golang.org/x/tools/go/packages/loadmode_string.go +++ b/vendor/golang.org/x/tools/go/packages/loadmode_string.go @@ -9,49 +9,48 @@ import ( "strings" ) -var allModes = []LoadMode{ - NeedName, - NeedFiles, - NeedCompiledGoFiles, - NeedImports, - NeedDeps, - NeedExportFile, - NeedTypes, - NeedSyntax, - NeedTypesInfo, - NeedTypesSizes, +var modes = [...]struct { + mode LoadMode + name string +}{ + {NeedName, "NeedName"}, + {NeedFiles, "NeedFiles"}, + {NeedCompiledGoFiles, "NeedCompiledGoFiles"}, + {NeedImports, "NeedImports"}, + {NeedDeps, "NeedDeps"}, + {NeedExportFile, "NeedExportFile"}, + {NeedTypes, "NeedTypes"}, + {NeedSyntax, "NeedSyntax"}, + {NeedTypesInfo, "NeedTypesInfo"}, + {NeedTypesSizes, "NeedTypesSizes"}, + {NeedForTest, "NeedForTest"}, + {NeedModule, "NeedModule"}, + {NeedEmbedFiles, "NeedEmbedFiles"}, + {NeedEmbedPatterns, "NeedEmbedPatterns"}, + {NeedTarget, "NeedTarget"}, } -var modeStrings = []string{ - "NeedName", - "NeedFiles", - "NeedCompiledGoFiles", - "NeedImports", - "NeedDeps", - "NeedExportFile", - "NeedTypes", - "NeedSyntax", - "NeedTypesInfo", - "NeedTypesSizes", -} - -func (mod LoadMode) String() string { - m := mod - if m == 0 { +func (mode LoadMode) String() string { + if mode == 0 { return "LoadMode(0)" } var out []string - for i, x := range allModes { - if x > m { - break + // named bits + for _, item := range modes { + if (mode & item.mode) != 0 { + mode ^= item.mode + out = append(out, item.name) } - if (m & x) != 0 { - out = append(out, modeStrings[i]) - m = m ^ x + } + // unnamed residue + if mode != 0 { + if out == nil { + return fmt.Sprintf("LoadMode(%#x)", int(mode)) } + out = append(out, fmt.Sprintf("%#x", int(mode))) } - if m != 0 { - out = append(out, "Unknown") + if len(out) == 1 { + return out[0] } - return fmt.Sprintf("LoadMode(%s)", strings.Join(out, "|")) + return "(" + strings.Join(out, "|") + ")" } diff --git a/vendor/golang.org/x/tools/go/packages/packages.go b/vendor/golang.org/x/tools/go/packages/packages.go index 0b6bfaff80..c3a59b8ebf 100644 --- a/vendor/golang.org/x/tools/go/packages/packages.go +++ b/vendor/golang.org/x/tools/go/packages/packages.go @@ -16,13 +16,13 @@ import ( "go/scanner" "go/token" "go/types" - "io" "log" "os" "path/filepath" "runtime" "strings" "sync" + "sync/atomic" "time" "golang.org/x/sync/errgroup" @@ -31,7 +31,6 @@ import ( "golang.org/x/tools/internal/gocommand" "golang.org/x/tools/internal/packagesinternal" "golang.org/x/tools/internal/typesinternal" - "golang.org/x/tools/internal/versions" ) // A LoadMode controls the amount of detail to return when loading. @@ -44,19 +43,33 @@ import ( // ID and Errors (if present) will always be filled. // [Load] may return more information than requested. // +// The Mode flag is a union of several bits named NeedName, +// NeedFiles, and so on, each of which determines whether +// a given field of Package (Name, Files, etc) should be +// populated. +// +// For convenience, we provide named constants for the most +// common combinations of Need flags: +// +// [LoadFiles] lists of files in each package +// [LoadImports] ... plus imports +// [LoadTypes] ... plus type information +// [LoadSyntax] ... plus type-annotated syntax +// [LoadAllSyntax] ... for all dependencies +// // Unfortunately there are a number of open bugs related to // interactions among the LoadMode bits: -// - https://github.com/golang/go/issues/56633 -// - https://github.com/golang/go/issues/56677 -// - https://github.com/golang/go/issues/58726 -// - https://github.com/golang/go/issues/63517 +// - https://go.dev/issue/56633 +// - https://go.dev/issue/56677 +// - https://go.dev/issue/58726 +// - https://go.dev/issue/63517 type LoadMode int const ( // NeedName adds Name and PkgPath. NeedName LoadMode = 1 << iota - // NeedFiles adds GoFiles and OtherFiles. + // NeedFiles adds Dir, GoFiles, OtherFiles, and IgnoredFiles NeedFiles // NeedCompiledGoFiles adds CompiledGoFiles. @@ -78,7 +91,7 @@ const ( // NeedSyntax adds Syntax and Fset. NeedSyntax - // NeedTypesInfo adds TypesInfo. + // NeedTypesInfo adds TypesInfo and Fset. NeedTypesInfo // NeedTypesSizes adds TypesSizes. @@ -87,9 +100,10 @@ const ( // needInternalDepsErrors adds the internal deps errors field for use by gopls. needInternalDepsErrors - // needInternalForTest adds the internal forTest field. + // NeedForTest adds ForTest. + // // Tests must also be set on the context for this field to be populated. - needInternalForTest + NeedForTest // typecheckCgo enables full support for type checking cgo. Requires Go 1.15+. // Modifies CompiledGoFiles and Types, and has no effect on its own. @@ -103,27 +117,27 @@ const ( // NeedEmbedPatterns adds EmbedPatterns. NeedEmbedPatterns + + // NeedTarget adds Target. + NeedTarget + + // Be sure to update loadmode_string.go when adding new items! ) const ( - // Deprecated: LoadFiles exists for historical compatibility - // and should not be used. Please directly specify the needed fields using the Need values. + // LoadFiles loads the name and file names for the initial packages. LoadFiles = NeedName | NeedFiles | NeedCompiledGoFiles - // Deprecated: LoadImports exists for historical compatibility - // and should not be used. Please directly specify the needed fields using the Need values. + // LoadImports loads the name, file names, and import mapping for the initial packages. LoadImports = LoadFiles | NeedImports - // Deprecated: LoadTypes exists for historical compatibility - // and should not be used. Please directly specify the needed fields using the Need values. + // LoadTypes loads exported type information for the initial packages. LoadTypes = LoadImports | NeedTypes | NeedTypesSizes - // Deprecated: LoadSyntax exists for historical compatibility - // and should not be used. Please directly specify the needed fields using the Need values. + // LoadSyntax loads typed syntax for the initial packages. LoadSyntax = LoadTypes | NeedSyntax | NeedTypesInfo - // Deprecated: LoadAllSyntax exists for historical compatibility - // and should not be used. Please directly specify the needed fields using the Need values. + // LoadAllSyntax loads typed syntax for the initial packages and all dependencies. LoadAllSyntax = LoadSyntax | NeedDeps // Deprecated: NeedExportsFile is a historical misspelling of NeedExportFile. @@ -133,13 +147,7 @@ const ( // A Config specifies details about how packages should be loaded. // The zero value is a valid configuration. // -// Calls to Load do not modify this struct. -// -// TODO(adonovan): #67702: this is currently false: in fact, -// calls to [Load] do not modify the public fields of this struct, but -// may modify hidden fields, so concurrent calls to [Load] must not -// use the same Config. But perhaps we should reestablish the -// documented invariant. +// Calls to [Load] do not modify this struct. type Config struct { // Mode controls the level of information returned for each package. Mode LoadMode @@ -170,19 +178,10 @@ type Config struct { // Env []string - // gocmdRunner guards go command calls from concurrency errors. - gocmdRunner *gocommand.Runner - // BuildFlags is a list of command-line flags to be passed through to // the build system's query tool. BuildFlags []string - // modFile will be used for -modfile in go command invocations. - modFile string - - // modFlag will be used for -modfile in go command invocations. - modFlag string - // Fset provides source position information for syntax trees and types. // If Fset is nil, Load will use a new fileset, but preserve Fset's value. Fset *token.FileSet @@ -229,21 +228,24 @@ type Config struct { // drivers may vary in their level of support for overlays. Overlay map[string][]byte - // goListOverlayFile is the JSON file that encodes the Overlay - // mapping, used by 'go list -overlay=...' - goListOverlayFile string + // -- Hidden configuration fields only for use in x/tools -- + + // modFile will be used for -modfile in go command invocations. + modFile string + + // modFlag will be used for -modfile in go command invocations. + modFlag string } // Load loads and returns the Go packages named by the given patterns. // -// Config specifies loading options; -// nil behaves the same as an empty Config. +// The cfg parameter specifies loading options; nil behaves the same as an empty [Config]. // // The [Config.Mode] field is a set of bits that determine what kinds // of information should be computed and returned. Modes that require // more information tend to be slower. See [LoadMode] for details // and important caveats. Its zero value is equivalent to -// NeedName | NeedFiles | NeedCompiledGoFiles. +// [NeedName] | [NeedFiles] | [NeedCompiledGoFiles]. // // Each call to Load returns a new set of [Package] instances. // The Packages and their Imports form a directed acyclic graph. @@ -260,7 +262,7 @@ type Config struct { // Errors associated with a particular package are recorded in the // corresponding Package's Errors list, and do not cause Load to // return an error. Clients may need to handle such errors before -// proceeding with further analysis. The PrintErrors function is +// proceeding with further analysis. The [PrintErrors] function is // provided for convenient display of all errors. func Load(cfg *Config, patterns ...string) ([]*Package, error) { ld := newLoader(cfg) @@ -323,21 +325,24 @@ func defaultDriver(cfg *Config, patterns ...string) (*DriverResponse, bool, erro } else if !response.NotHandled { return response, true, nil } - // (fall through) + // not handled: fall through } // go list fallback - // + // Write overlays once, as there are many calls // to 'go list' (one per chunk plus others too). - overlay, cleanupOverlay, err := gocommand.WriteOverlays(cfg.Overlay) + overlayFile, cleanupOverlay, err := gocommand.WriteOverlays(cfg.Overlay) if err != nil { return nil, false, err } defer cleanupOverlay() - cfg.goListOverlayFile = overlay - response, err := callDriverOnChunks(goListDriver, cfg, chunks) + var runner gocommand.Runner // (shared across many 'go list' calls) + driver := func(cfg *Config, patterns []string) (*DriverResponse, error) { + return goListDriver(cfg, &runner, overlayFile, patterns) + } + response, err := callDriverOnChunks(driver, cfg, chunks) if err != nil { return nil, false, err } @@ -375,16 +380,14 @@ func splitIntoChunks(patterns []string, argMax int) ([][]string, error) { func callDriverOnChunks(driver driver, cfg *Config, chunks [][]string) (*DriverResponse, error) { if len(chunks) == 0 { - return driver(cfg) + return driver(cfg, nil) } responses := make([]*DriverResponse, len(chunks)) errNotHandled := errors.New("driver returned NotHandled") var g errgroup.Group for i, chunk := range chunks { - i := i - chunk := chunk g.Go(func() (err error) { - responses[i], err = driver(cfg, chunk...) + responses[i], err = driver(cfg, chunk) if responses[i] != nil && responses[i].NotHandled { err = errNotHandled } @@ -434,6 +437,12 @@ type Package struct { // PkgPath is the package path as used by the go/types package. PkgPath string + // Dir is the directory associated with the package, if it exists. + // + // For packages listed by the go command, this is the directory containing + // the package files. + Dir string + // Errors contains any errors encountered querying the metadata // of the package, or while parsing or type-checking its files. Errors []Error @@ -473,6 +482,10 @@ type Package struct { // information for the package as provided by the build system. ExportFile string + // Target is the absolute install path of the .a file, for libraries, + // and of the executable file, for binaries. + Target string + // Imports maps import paths appearing in the package's Go source files // to corresponding loaded Packages. Imports map[string]*Package @@ -521,8 +534,8 @@ type Package struct { // -- internal -- - // forTest is the package under test, if any. - forTest string + // ForTest is the package under test, if any. + ForTest string // depsErrors is the DepsErrors field from the go list response, if any. depsErrors []*packagesinternal.PackageError @@ -551,9 +564,6 @@ type ModuleError struct { } func init() { - packagesinternal.GetForTest = func(p interface{}) string { - return p.(*Package).forTest - } packagesinternal.GetDepsErrors = func(p interface{}) []*packagesinternal.PackageError { return p.(*Package).depsErrors } @@ -565,7 +575,6 @@ func init() { } packagesinternal.TypecheckCgo = int(typecheckCgo) packagesinternal.DepsErrors = int(needInternalDepsErrors) - packagesinternal.ForTest = int(needInternalForTest) } // An Error describes a problem with a package's metadata, syntax, or types. @@ -681,18 +690,19 @@ func (p *Package) String() string { return p.ID } // loaderPackage augments Package with state used during the loading phase type loaderPackage struct { *Package - importErrors map[string]error // maps each bad import to its error - loadOnce sync.Once - color uint8 // for cycle detection - needsrc bool // load from source (Mode >= LoadTypes) - needtypes bool // type information is either requested or depended on - initial bool // package was matched by a pattern - goVersion int // minor version number of go command on PATH + importErrors map[string]error // maps each bad import to its error + preds []*loaderPackage // packages that import this one + unfinishedSuccs atomic.Int32 // number of direct imports not yet loaded + color uint8 // for cycle detection + needsrc bool // load from source (Mode >= LoadTypes) + needtypes bool // type information is either requested or depended on + initial bool // package was matched by a pattern + goVersion int // minor version number of go command on PATH } // loader holds the working state of a single call to load. type loader struct { - pkgs map[string]*loaderPackage + pkgs map[string]*loaderPackage // keyed by Package.ID Config sizes types.Sizes // non-nil if needed by mode parseCache map[string]*parseValue @@ -738,9 +748,6 @@ func newLoader(cfg *Config) *loader { if ld.Config.Env == nil { ld.Config.Env = os.Environ() } - if ld.Config.gocmdRunner == nil { - ld.Config.gocmdRunner = &gocommand.Runner{} - } if ld.Context == nil { ld.Context = context.Background() } @@ -754,7 +761,7 @@ func newLoader(cfg *Config) *loader { ld.requestedMode = ld.Mode ld.Mode = impliedLoadMode(ld.Mode) - if ld.Mode&NeedTypes != 0 || ld.Mode&NeedSyntax != 0 { + if ld.Mode&(NeedSyntax|NeedTypes|NeedTypesInfo) != 0 { if ld.Fset == nil { ld.Fset = token.NewFileSet() } @@ -763,6 +770,7 @@ func newLoader(cfg *Config) *loader { // because we load source if export data is missing. if ld.ParseFile == nil { ld.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) { + // We implicitly promise to keep doing ast.Object resolution. :( const mode = parser.AllErrors | parser.ParseComments return parser.ParseFile(fset, filename, src, mode) } @@ -794,7 +802,7 @@ func (ld *loader) refine(response *DriverResponse) ([]*Package, error) { exportDataInvalid := len(ld.Overlay) > 0 || pkg.ExportFile == "" && pkg.PkgPath != "unsafe" // This package needs type information if the caller requested types and the package is // either a root, or it's a non-root and the user requested dependencies ... - needtypes := (ld.Mode&NeedTypes|NeedTypesInfo != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0)) + needtypes := (ld.Mode&(NeedTypes|NeedTypesInfo) != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0)) // This package needs source if the call requested source (or types info, which implies source) // and the package is either a root, or itas a non- root and the user requested dependencies... needsrc := ((ld.Mode&(NeedSyntax|NeedTypesInfo) != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0)) || @@ -819,9 +827,10 @@ func (ld *loader) refine(response *DriverResponse) ([]*Package, error) { } } - if ld.Mode&NeedImports != 0 { - // Materialize the import graph. - + // Materialize the import graph if it is needed (NeedImports), + // or if we'll be using loadPackages (Need{Syntax|Types|TypesInfo}). + var leaves []*loaderPackage // packages with no unfinished successors + if ld.Mode&(NeedImports|NeedSyntax|NeedTypes|NeedTypesInfo) != 0 { const ( white = 0 // new grey = 1 // in progress @@ -840,63 +849,76 @@ func (ld *loader) refine(response *DriverResponse) ([]*Package, error) { // dependency on a package that does. These are the only packages // for which we load source code. var stack []*loaderPackage - var visit func(lpkg *loaderPackage) bool - visit = func(lpkg *loaderPackage) bool { - switch lpkg.color { - case black: - return lpkg.needsrc - case grey: + var visit func(from, lpkg *loaderPackage) bool + visit = func(from, lpkg *loaderPackage) bool { + if lpkg.color == grey { panic("internal error: grey node") } - lpkg.color = grey - stack = append(stack, lpkg) // push - stubs := lpkg.Imports // the structure form has only stubs with the ID in the Imports - lpkg.Imports = make(map[string]*Package, len(stubs)) - for importPath, ipkg := range stubs { - var importErr error - imp := ld.pkgs[ipkg.ID] - if imp == nil { - // (includes package "C" when DisableCgo) - importErr = fmt.Errorf("missing package: %q", ipkg.ID) - } else if imp.color == grey { - importErr = fmt.Errorf("import cycle: %s", stack) + if lpkg.color == white { + lpkg.color = grey + stack = append(stack, lpkg) // push + stubs := lpkg.Imports // the structure form has only stubs with the ID in the Imports + lpkg.Imports = make(map[string]*Package, len(stubs)) + for importPath, ipkg := range stubs { + var importErr error + imp := ld.pkgs[ipkg.ID] + if imp == nil { + // (includes package "C" when DisableCgo) + importErr = fmt.Errorf("missing package: %q", ipkg.ID) + } else if imp.color == grey { + importErr = fmt.Errorf("import cycle: %s", stack) + } + if importErr != nil { + if lpkg.importErrors == nil { + lpkg.importErrors = make(map[string]error) + } + lpkg.importErrors[importPath] = importErr + continue + } + + if visit(lpkg, imp) { + lpkg.needsrc = true + } + lpkg.Imports[importPath] = imp.Package } - if importErr != nil { - if lpkg.importErrors == nil { - lpkg.importErrors = make(map[string]error) + + // -- postorder -- + + // Complete type information is required for the + // immediate dependencies of each source package. + if lpkg.needsrc && ld.Mode&NeedTypes != 0 { + for _, ipkg := range lpkg.Imports { + ld.pkgs[ipkg.ID].needtypes = true } - lpkg.importErrors[importPath] = importErr - continue } - if visit(imp) { - lpkg.needsrc = true + // NeedTypeSizes causes TypeSizes to be set even + // on packages for which types aren't needed. + if ld.Mode&NeedTypesSizes != 0 { + lpkg.TypesSizes = ld.sizes } - lpkg.Imports[importPath] = imp.Package - } - // Complete type information is required for the - // immediate dependencies of each source package. - if lpkg.needsrc && ld.Mode&NeedTypes != 0 { - for _, ipkg := range lpkg.Imports { - ld.pkgs[ipkg.ID].needtypes = true + // Add packages with no imports directly to the queue of leaves. + if len(lpkg.Imports) == 0 { + leaves = append(leaves, lpkg) } + + stack = stack[:len(stack)-1] // pop + lpkg.color = black } - // NeedTypeSizes causes TypeSizes to be set even - // on packages for which types aren't needed. - if ld.Mode&NeedTypesSizes != 0 { - lpkg.TypesSizes = ld.sizes + // Add edge from predecessor. + if from != nil { + from.unfinishedSuccs.Add(+1) // incref + lpkg.preds = append(lpkg.preds, from) } - stack = stack[:len(stack)-1] // pop - lpkg.color = black return lpkg.needsrc } // For each initial package, create its import DAG. for _, lpkg := range initial { - visit(lpkg) + visit(nil, lpkg) } } else { @@ -909,16 +931,45 @@ func (ld *loader) refine(response *DriverResponse) ([]*Package, error) { // Load type data and syntax if needed, starting at // the initial packages (roots of the import DAG). - if ld.Mode&NeedTypes != 0 || ld.Mode&NeedSyntax != 0 { - var wg sync.WaitGroup - for _, lpkg := range initial { - wg.Add(1) - go func(lpkg *loaderPackage) { - ld.loadRecursive(lpkg) - wg.Done() - }(lpkg) + if ld.Mode&(NeedSyntax|NeedTypes|NeedTypesInfo) != 0 { + + // We avoid using g.SetLimit to limit concurrency as + // it makes g.Go stop accepting work, which prevents + // workers from enqeuing, and thus finishing, and thus + // allowing the group to make progress: deadlock. + // + // Instead we use the ioLimit and cpuLimit semaphores. + g, _ := errgroup.WithContext(ld.Context) + + // enqueues adds a package to the type-checking queue. + // It must have no unfinished successors. + var enqueue func(*loaderPackage) + enqueue = func(lpkg *loaderPackage) { + g.Go(func() error { + // Parse and type-check. + ld.loadPackage(lpkg) + + // Notify each waiting predecessor, + // and enqueue it when it becomes a leaf. + for _, pred := range lpkg.preds { + if pred.unfinishedSuccs.Add(-1) == 0 { // decref + enqueue(pred) + } + } + + return nil + }) + } + + // Load leaves first, adding new packages + // to the queue as they become leaves. + for _, leaf := range leaves { + enqueue(leaf) + } + + if err := g.Wait(); err != nil { + return nil, err // cancelled } - wg.Wait() } // If the context is done, return its error and @@ -965,7 +1016,7 @@ func (ld *loader) refine(response *DriverResponse) ([]*Package, error) { if ld.requestedMode&NeedSyntax == 0 { ld.pkgs[i].Syntax = nil } - if ld.requestedMode&NeedTypes == 0 && ld.requestedMode&NeedSyntax == 0 { + if ld.requestedMode&(NeedSyntax|NeedTypes|NeedTypesInfo) == 0 { ld.pkgs[i].Fset = nil } if ld.requestedMode&NeedTypesInfo == 0 { @@ -982,31 +1033,10 @@ func (ld *loader) refine(response *DriverResponse) ([]*Package, error) { return result, nil } -// loadRecursive loads the specified package and its dependencies, -// recursively, in parallel, in topological order. -// It is atomic and idempotent. -// Precondition: ld.Mode&NeedTypes. -func (ld *loader) loadRecursive(lpkg *loaderPackage) { - lpkg.loadOnce.Do(func() { - // Load the direct dependencies, in parallel. - var wg sync.WaitGroup - for _, ipkg := range lpkg.Imports { - imp := ld.pkgs[ipkg.ID] - wg.Add(1) - go func(imp *loaderPackage) { - ld.loadRecursive(imp) - wg.Done() - }(imp) - } - wg.Wait() - ld.loadPackage(lpkg) - }) -} - -// loadPackage loads the specified package. +// loadPackage loads/parses/typechecks the specified package. // It must be called only once per Package, // after immediate dependencies are loaded. -// Precondition: ld.Mode & NeedTypes. +// Precondition: ld.Mode&(NeedSyntax|NeedTypes|NeedTypesInfo) != 0. func (ld *loader) loadPackage(lpkg *loaderPackage) { if lpkg.PkgPath == "unsafe" { // Fill in the blanks to avoid surprises. @@ -1042,6 +1072,10 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { if !lpkg.needtypes && !lpkg.needsrc { return } + + // TODO(adonovan): this condition looks wrong: + // I think it should be lpkg.needtypes && !lpg.needsrc, + // so that NeedSyntax without NeedTypes can be satisfied by export data. if !lpkg.needsrc { if err := ld.loadFromExportData(lpkg); err != nil { lpkg.Errors = append(lpkg.Errors, Error{ @@ -1147,7 +1181,7 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { } lpkg.Syntax = files - if ld.Config.Mode&NeedTypes == 0 { + if ld.Config.Mode&(NeedTypes|NeedTypesInfo) == 0 { return } @@ -1158,16 +1192,20 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { return } - lpkg.TypesInfo = &types.Info{ - Types: make(map[ast.Expr]types.TypeAndValue), - Defs: make(map[*ast.Ident]types.Object), - Uses: make(map[*ast.Ident]types.Object), - Implicits: make(map[ast.Node]types.Object), - Instances: make(map[*ast.Ident]types.Instance), - Scopes: make(map[ast.Node]*types.Scope), - Selections: make(map[*ast.SelectorExpr]*types.Selection), + // Populate TypesInfo only if needed, as it + // causes the type checker to work much harder. + if ld.Config.Mode&NeedTypesInfo != 0 { + lpkg.TypesInfo = &types.Info{ + Types: make(map[ast.Expr]types.TypeAndValue), + Defs: make(map[*ast.Ident]types.Object), + Uses: make(map[*ast.Ident]types.Object), + Implicits: make(map[ast.Node]types.Object), + Instances: make(map[*ast.Ident]types.Instance), + Scopes: make(map[ast.Node]*types.Scope), + Selections: make(map[*ast.SelectorExpr]*types.Selection), + FileVersions: make(map[*ast.File]string), + } } - versions.InitFileVersions(lpkg.TypesInfo) lpkg.TypesSizes = ld.sizes importer := importerFunc(func(path string) (*types.Package, error) { @@ -1220,6 +1258,10 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { } } + // Type-checking is CPU intensive. + cpuLimit <- unit{} // acquire a token + defer func() { <-cpuLimit }() // release a token + typErr := types.NewChecker(tc, ld.Fset, lpkg.Types, lpkg.TypesInfo).Files(lpkg.Syntax) lpkg.importErrors = nil // no longer needed @@ -1284,8 +1326,11 @@ type importerFunc func(path string) (*types.Package, error) func (f importerFunc) Import(path string) (*types.Package, error) { return f(path) } // We use a counting semaphore to limit -// the number of parallel I/O calls per process. -var ioLimit = make(chan bool, 20) +// the number of parallel I/O calls or CPU threads per process. +var ( + ioLimit = make(chan unit, 20) + cpuLimit = make(chan unit, runtime.GOMAXPROCS(0)) +) func (ld *loader) parseFile(filename string) (*ast.File, error) { ld.parseCacheMu.Lock() @@ -1302,20 +1347,28 @@ func (ld *loader) parseFile(filename string) (*ast.File, error) { var src []byte for f, contents := range ld.Config.Overlay { + // TODO(adonovan): Inefficient for large overlays. + // Do an exact name-based map lookup + // (for nonexistent files) followed by a + // FileID-based map lookup (for existing ones). if sameFile(f, filename) { src = contents + break } } var err error if src == nil { - ioLimit <- true // wait + ioLimit <- unit{} // acquire a token src, err = os.ReadFile(filename) - <-ioLimit // signal + <-ioLimit // release a token } if err != nil { v.err = err } else { + // Parsing is CPU intensive. + cpuLimit <- unit{} // acquire a token v.f, v.err = ld.ParseFile(ld.Fset, filename, src) + <-cpuLimit // release a token } close(v.ready) @@ -1330,18 +1383,21 @@ func (ld *loader) parseFile(filename string) (*ast.File, error) { // Because files are scanned in parallel, the token.Pos // positions of the resulting ast.Files are not ordered. func (ld *loader) parseFiles(filenames []string) ([]*ast.File, []error) { - var wg sync.WaitGroup - n := len(filenames) - parsed := make([]*ast.File, n) - errors := make([]error, n) - for i, file := range filenames { - wg.Add(1) - go func(i int, filename string) { + var ( + n = len(filenames) + parsed = make([]*ast.File, n) + errors = make([]error, n) + ) + var g errgroup.Group + for i, filename := range filenames { + // This creates goroutines unnecessarily in the + // cache-hit case, but that case is uncommon. + g.Go(func() error { parsed[i], errors[i] = ld.parseFile(filename) - wg.Done() - }(i, file) + return nil + }) } - wg.Wait() + g.Wait() // Eliminate nils, preserving order. var o int @@ -1512,4 +1568,4 @@ func usesExportData(cfg *Config) bool { return cfg.Mode&NeedExportFile != 0 || cfg.Mode&NeedTypes != 0 && cfg.Mode&NeedDeps == 0 } -var _ interface{} = io.Discard // assert build toolchain is go1.16 or later +type unit struct{} diff --git a/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go b/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go index 9ada177758..16ed3c1780 100644 --- a/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go +++ b/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go @@ -228,7 +228,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) { // Reject obviously non-viable cases. switch obj := obj.(type) { case *types.TypeName: - if _, ok := aliases.Unalias(obj.Type()).(*types.TypeParam); !ok { + if _, ok := types.Unalias(obj.Type()).(*types.TypeParam); !ok { // With the exception of type parameters, only package-level type names // have a path. return "", fmt.Errorf("no path for %v", obj) @@ -280,26 +280,26 @@ func (enc *Encoder) For(obj types.Object) (Path, error) { path = append(path, opType) T := o.Type() - if alias, ok := T.(*aliases.Alias); ok { - if r := findTypeParam(obj, aliases.TypeParams(alias), path, opTypeParam, nil); r != nil { + if alias, ok := T.(*types.Alias); ok { + if r := findTypeParam(obj, aliases.TypeParams(alias), path, opTypeParam); r != nil { return Path(r), nil } - if r := find(obj, aliases.Rhs(alias), append(path, opRhs), nil); r != nil { + if r := find(obj, aliases.Rhs(alias), append(path, opRhs)); r != nil { return Path(r), nil } } else if tname.IsAlias() { // legacy alias - if r := find(obj, T, path, nil); r != nil { + if r := find(obj, T, path); r != nil { return Path(r), nil } } else if named, ok := T.(*types.Named); ok { // defined (named) type - if r := findTypeParam(obj, named.TypeParams(), path, opTypeParam, nil); r != nil { + if r := findTypeParam(obj, named.TypeParams(), path, opTypeParam); r != nil { return Path(r), nil } - if r := find(obj, named.Underlying(), append(path, opUnderlying), nil); r != nil { + if r := find(obj, named.Underlying(), append(path, opUnderlying)); r != nil { return Path(r), nil } } @@ -312,7 +312,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) { if _, ok := o.(*types.TypeName); !ok { if o.Exported() { // exported non-type (const, var, func) - if r := find(obj, o.Type(), append(path, opType), nil); r != nil { + if r := find(obj, o.Type(), append(path, opType)); r != nil { return Path(r), nil } } @@ -320,7 +320,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) { } // Inspect declared methods of defined types. - if T, ok := aliases.Unalias(o.Type()).(*types.Named); ok { + if T, ok := types.Unalias(o.Type()).(*types.Named); ok { path = append(path, opType) // The method index here is always with respect // to the underlying go/types data structures, @@ -332,7 +332,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) { if m == obj { return Path(path2), nil // found declared method } - if r := find(obj, m.Type(), append(path2, opType), nil); r != nil { + if r := find(obj, m.Type(), append(path2, opType)); r != nil { return Path(r), nil } } @@ -447,46 +447,64 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) { // // The seen map is used to short circuit cycles through type parameters. If // nil, it will be allocated as necessary. -func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]bool) []byte { +// +// The seenMethods map is used internally to short circuit cycles through +// interface methods, such as occur in the following example: +// +// type I interface { f() interface{I} } +// +// See golang/go#68046 for details. +func find(obj types.Object, T types.Type, path []byte) []byte { + return (&finder{obj: obj}).find(T, path) +} + +// finder closes over search state for a call to find. +type finder struct { + obj types.Object // the sought object + seenTParamNames map[*types.TypeName]bool // for cycle breaking through type parameters + seenMethods map[*types.Func]bool // for cycle breaking through recursive interfaces +} + +func (f *finder) find(T types.Type, path []byte) []byte { switch T := T.(type) { - case *aliases.Alias: - return find(obj, aliases.Unalias(T), path, seen) + case *types.Alias: + return f.find(types.Unalias(T), path) case *types.Basic, *types.Named: // Named types belonging to pkg were handled already, // so T must belong to another package. No path. return nil case *types.Pointer: - return find(obj, T.Elem(), append(path, opElem), seen) + return f.find(T.Elem(), append(path, opElem)) case *types.Slice: - return find(obj, T.Elem(), append(path, opElem), seen) + return f.find(T.Elem(), append(path, opElem)) case *types.Array: - return find(obj, T.Elem(), append(path, opElem), seen) + return f.find(T.Elem(), append(path, opElem)) case *types.Chan: - return find(obj, T.Elem(), append(path, opElem), seen) + return f.find(T.Elem(), append(path, opElem)) case *types.Map: - if r := find(obj, T.Key(), append(path, opKey), seen); r != nil { + if r := f.find(T.Key(), append(path, opKey)); r != nil { return r } - return find(obj, T.Elem(), append(path, opElem), seen) + return f.find(T.Elem(), append(path, opElem)) case *types.Signature: - if r := findTypeParam(obj, T.RecvTypeParams(), path, opRecvTypeParam, nil); r != nil { + if r := f.findTypeParam(T.RecvTypeParams(), path, opRecvTypeParam); r != nil { return r } - if r := findTypeParam(obj, T.TypeParams(), path, opTypeParam, seen); r != nil { + if r := f.findTypeParam(T.TypeParams(), path, opTypeParam); r != nil { return r } - if r := find(obj, T.Params(), append(path, opParams), seen); r != nil { + if r := f.find(T.Params(), append(path, opParams)); r != nil { return r } - return find(obj, T.Results(), append(path, opResults), seen) + return f.find(T.Results(), append(path, opResults)) case *types.Struct: for i := 0; i < T.NumFields(); i++ { fld := T.Field(i) path2 := appendOpArg(path, opField, i) - if fld == obj { + if fld == f.obj { return path2 // found field var } - if r := find(obj, fld.Type(), append(path2, opType), seen); r != nil { + if r := f.find(fld.Type(), append(path2, opType)); r != nil { return r } } @@ -495,10 +513,10 @@ func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName] for i := 0; i < T.Len(); i++ { v := T.At(i) path2 := appendOpArg(path, opAt, i) - if v == obj { + if v == f.obj { return path2 // found param/result var } - if r := find(obj, v.Type(), append(path2, opType), seen); r != nil { + if r := f.find(v.Type(), append(path2, opType)); r != nil { return r } } @@ -506,28 +524,35 @@ func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName] case *types.Interface: for i := 0; i < T.NumMethods(); i++ { m := T.Method(i) + if f.seenMethods[m] { + return nil + } path2 := appendOpArg(path, opMethod, i) - if m == obj { + if m == f.obj { return path2 // found interface method } - if r := find(obj, m.Type(), append(path2, opType), seen); r != nil { + if f.seenMethods == nil { + f.seenMethods = make(map[*types.Func]bool) + } + f.seenMethods[m] = true + if r := f.find(m.Type(), append(path2, opType)); r != nil { return r } } return nil case *types.TypeParam: name := T.Obj() - if name == obj { - return append(path, opObj) - } - if seen[name] { + if f.seenTParamNames[name] { return nil } - if seen == nil { - seen = make(map[*types.TypeName]bool) + if name == f.obj { + return append(path, opObj) } - seen[name] = true - if r := find(obj, T.Constraint(), append(path, opConstraint), seen); r != nil { + if f.seenTParamNames == nil { + f.seenTParamNames = make(map[*types.TypeName]bool) + } + f.seenTParamNames[name] = true + if r := f.find(T.Constraint(), append(path, opConstraint)); r != nil { return r } return nil @@ -535,11 +560,15 @@ func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName] panic(T) } -func findTypeParam(obj types.Object, list *types.TypeParamList, path []byte, op byte, seen map[*types.TypeName]bool) []byte { +func findTypeParam(obj types.Object, list *types.TypeParamList, path []byte, op byte) []byte { + return (&finder{obj: obj}).findTypeParam(list, path, op) +} + +func (f *finder) findTypeParam(list *types.TypeParamList, path []byte, op byte) []byte { for i := 0; i < list.Len(); i++ { tparam := list.At(i) path2 := appendOpArg(path, op, i) - if r := find(obj, tparam, path2, seen); r != nil { + if r := f.find(tparam, path2); r != nil { return r } } @@ -626,7 +655,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) { // Inv: t != nil, obj == nil - t = aliases.Unalias(t) + t = types.Unalias(t) switch code { case opElem: hasElem, ok := t.(hasElem) // Pointer, Slice, Array, Chan, Map @@ -664,7 +693,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) { t = named.Underlying() case opRhs: - if alias, ok := t.(*aliases.Alias); ok { + if alias, ok := t.(*types.Alias); ok { t = aliases.Rhs(alias) } else if false && aliases.Enabled() { // The Enabled check is too expensive, so for now we diff --git a/vendor/golang.org/x/tools/go/types/typeutil/callee.go b/vendor/golang.org/x/tools/go/types/typeutil/callee.go new file mode 100644 index 0000000000..754380351e --- /dev/null +++ b/vendor/golang.org/x/tools/go/types/typeutil/callee.go @@ -0,0 +1,68 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package typeutil + +import ( + "go/ast" + "go/types" + + "golang.org/x/tools/internal/typeparams" +) + +// Callee returns the named target of a function call, if any: +// a function, method, builtin, or variable. +// +// Functions and methods may potentially have type parameters. +func Callee(info *types.Info, call *ast.CallExpr) types.Object { + fun := ast.Unparen(call.Fun) + + // Look through type instantiation if necessary. + isInstance := false + switch fun.(type) { + case *ast.IndexExpr, *ast.IndexListExpr: + // When extracting the callee from an *IndexExpr, we need to check that + // it is a *types.Func and not a *types.Var. + // Example: Don't match a slice m within the expression `m[0]()`. + isInstance = true + fun, _, _, _ = typeparams.UnpackIndexExpr(fun) + } + + var obj types.Object + switch fun := fun.(type) { + case *ast.Ident: + obj = info.Uses[fun] // type, var, builtin, or declared func + case *ast.SelectorExpr: + if sel, ok := info.Selections[fun]; ok { + obj = sel.Obj() // method or field + } else { + obj = info.Uses[fun.Sel] // qualified identifier? + } + } + if _, ok := obj.(*types.TypeName); ok { + return nil // T(x) is a conversion, not a call + } + // A Func is required to match instantiations. + if _, ok := obj.(*types.Func); isInstance && !ok { + return nil // Was not a Func. + } + return obj +} + +// StaticCallee returns the target (function or method) of a static function +// call, if any. It returns nil for calls to builtins. +// +// Note: for calls of instantiated functions and methods, StaticCallee returns +// the corresponding generic function or method on the generic type. +func StaticCallee(info *types.Info, call *ast.CallExpr) *types.Func { + if f, ok := Callee(info, call).(*types.Func); ok && !interfaceMethod(f) { + return f + } + return nil +} + +func interfaceMethod(f *types.Func) bool { + recv := f.Type().(*types.Signature).Recv() + return recv != nil && types.IsInterface(recv.Type()) +} diff --git a/vendor/golang.org/x/tools/go/types/typeutil/imports.go b/vendor/golang.org/x/tools/go/types/typeutil/imports.go new file mode 100644 index 0000000000..b81ce0c330 --- /dev/null +++ b/vendor/golang.org/x/tools/go/types/typeutil/imports.go @@ -0,0 +1,30 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package typeutil + +import "go/types" + +// Dependencies returns all dependencies of the specified packages. +// +// Dependent packages appear in topological order: if package P imports +// package Q, Q appears earlier than P in the result. +// The algorithm follows import statements in the order they +// appear in the source code, so the result is a total order. +func Dependencies(pkgs ...*types.Package) []*types.Package { + var result []*types.Package + seen := make(map[*types.Package]bool) + var visit func(pkgs []*types.Package) + visit = func(pkgs []*types.Package) { + for _, p := range pkgs { + if !seen[p] { + seen[p] = true + visit(p.Imports()) + result = append(result, p) + } + } + } + visit(pkgs) + return result +} diff --git a/vendor/golang.org/x/tools/go/types/typeutil/map.go b/vendor/golang.org/x/tools/go/types/typeutil/map.go new file mode 100644 index 0000000000..43261147c0 --- /dev/null +++ b/vendor/golang.org/x/tools/go/types/typeutil/map.go @@ -0,0 +1,470 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package typeutil defines various utilities for types, such as [Map], +// a hash table that maps [types.Type] to any value. +package typeutil + +import ( + "bytes" + "fmt" + "go/types" + "hash/maphash" + "unsafe" + + "golang.org/x/tools/internal/typeparams" +) + +// Map is a hash-table-based mapping from types (types.Type) to +// arbitrary values. The concrete types that implement +// the Type interface are pointers. Since they are not canonicalized, +// == cannot be used to check for equivalence, and thus we cannot +// simply use a Go map. +// +// Just as with map[K]V, a nil *Map is a valid empty map. +// +// Read-only map operations ([Map.At], [Map.Len], and so on) may +// safely be called concurrently. +// +// TODO(adonovan): deprecate in favor of https://go.dev/issues/69420 +// and 69559, if the latter proposals for a generic hash-map type and +// a types.Hash function are accepted. +type Map struct { + table map[uint32][]entry // maps hash to bucket; entry.key==nil means unused + length int // number of map entries +} + +// entry is an entry (key/value association) in a hash bucket. +type entry struct { + key types.Type + value any +} + +// SetHasher has no effect. +// +// It is a relic of an optimization that is no longer profitable. Do +// not use [Hasher], [MakeHasher], or [SetHasher] in new code. +func (m *Map) SetHasher(Hasher) {} + +// Delete removes the entry with the given key, if any. +// It returns true if the entry was found. +func (m *Map) Delete(key types.Type) bool { + if m != nil && m.table != nil { + hash := hash(key) + bucket := m.table[hash] + for i, e := range bucket { + if e.key != nil && types.Identical(key, e.key) { + // We can't compact the bucket as it + // would disturb iterators. + bucket[i] = entry{} + m.length-- + return true + } + } + } + return false +} + +// At returns the map entry for the given key. +// The result is nil if the entry is not present. +func (m *Map) At(key types.Type) any { + if m != nil && m.table != nil { + for _, e := range m.table[hash(key)] { + if e.key != nil && types.Identical(key, e.key) { + return e.value + } + } + } + return nil +} + +// Set sets the map entry for key to val, +// and returns the previous entry, if any. +func (m *Map) Set(key types.Type, value any) (prev any) { + if m.table != nil { + hash := hash(key) + bucket := m.table[hash] + var hole *entry + for i, e := range bucket { + if e.key == nil { + hole = &bucket[i] + } else if types.Identical(key, e.key) { + prev = e.value + bucket[i].value = value + return + } + } + + if hole != nil { + *hole = entry{key, value} // overwrite deleted entry + } else { + m.table[hash] = append(bucket, entry{key, value}) + } + } else { + hash := hash(key) + m.table = map[uint32][]entry{hash: {entry{key, value}}} + } + + m.length++ + return +} + +// Len returns the number of map entries. +func (m *Map) Len() int { + if m != nil { + return m.length + } + return 0 +} + +// Iterate calls function f on each entry in the map in unspecified order. +// +// If f should mutate the map, Iterate provides the same guarantees as +// Go maps: if f deletes a map entry that Iterate has not yet reached, +// f will not be invoked for it, but if f inserts a map entry that +// Iterate has not yet reached, whether or not f will be invoked for +// it is unspecified. +func (m *Map) Iterate(f func(key types.Type, value any)) { + if m != nil { + for _, bucket := range m.table { + for _, e := range bucket { + if e.key != nil { + f(e.key, e.value) + } + } + } + } +} + +// Keys returns a new slice containing the set of map keys. +// The order is unspecified. +func (m *Map) Keys() []types.Type { + keys := make([]types.Type, 0, m.Len()) + m.Iterate(func(key types.Type, _ any) { + keys = append(keys, key) + }) + return keys +} + +func (m *Map) toString(values bool) string { + if m == nil { + return "{}" + } + var buf bytes.Buffer + fmt.Fprint(&buf, "{") + sep := "" + m.Iterate(func(key types.Type, value any) { + fmt.Fprint(&buf, sep) + sep = ", " + fmt.Fprint(&buf, key) + if values { + fmt.Fprintf(&buf, ": %q", value) + } + }) + fmt.Fprint(&buf, "}") + return buf.String() +} + +// String returns a string representation of the map's entries. +// Values are printed using fmt.Sprintf("%v", v). +// Order is unspecified. +func (m *Map) String() string { + return m.toString(true) +} + +// KeysString returns a string representation of the map's key set. +// Order is unspecified. +func (m *Map) KeysString() string { + return m.toString(false) +} + +// -- Hasher -- + +// hash returns the hash of type t. +// TODO(adonovan): replace by types.Hash when Go proposal #69420 is accepted. +func hash(t types.Type) uint32 { + return theHasher.Hash(t) +} + +// A Hasher provides a [Hasher.Hash] method to map a type to its hash value. +// Hashers are stateless, and all are equivalent. +type Hasher struct{} + +var theHasher Hasher + +// MakeHasher returns Hasher{}. +// Hashers are stateless; all are equivalent. +func MakeHasher() Hasher { return theHasher } + +// Hash computes a hash value for the given type t such that +// Identical(t, t') => Hash(t) == Hash(t'). +func (h Hasher) Hash(t types.Type) uint32 { + return hasher{inGenericSig: false}.hash(t) +} + +// hasher holds the state of a single Hash traversal: whether we are +// inside the signature of a generic function; this is used to +// optimize [hasher.hashTypeParam]. +type hasher struct{ inGenericSig bool } + +// hashString computes the Fowler–Noll–Vo hash of s. +func hashString(s string) uint32 { + var h uint32 + for i := 0; i < len(s); i++ { + h ^= uint32(s[i]) + h *= 16777619 + } + return h +} + +// hash computes the hash of t. +func (h hasher) hash(t types.Type) uint32 { + // See Identical for rationale. + switch t := t.(type) { + case *types.Basic: + return uint32(t.Kind()) + + case *types.Alias: + return h.hash(types.Unalias(t)) + + case *types.Array: + return 9043 + 2*uint32(t.Len()) + 3*h.hash(t.Elem()) + + case *types.Slice: + return 9049 + 2*h.hash(t.Elem()) + + case *types.Struct: + var hash uint32 = 9059 + for i, n := 0, t.NumFields(); i < n; i++ { + f := t.Field(i) + if f.Anonymous() { + hash += 8861 + } + hash += hashString(t.Tag(i)) + hash += hashString(f.Name()) // (ignore f.Pkg) + hash += h.hash(f.Type()) + } + return hash + + case *types.Pointer: + return 9067 + 2*h.hash(t.Elem()) + + case *types.Signature: + var hash uint32 = 9091 + if t.Variadic() { + hash *= 8863 + } + + tparams := t.TypeParams() + if n := tparams.Len(); n > 0 { + h.inGenericSig = true // affects constraints, params, and results + + for i := range n { + tparam := tparams.At(i) + hash += 7 * h.hash(tparam.Constraint()) + } + } + + return hash + 3*h.hashTuple(t.Params()) + 5*h.hashTuple(t.Results()) + + case *types.Union: + return h.hashUnion(t) + + case *types.Interface: + // Interfaces are identical if they have the same set of methods, with + // identical names and types, and they have the same set of type + // restrictions. See go/types.identical for more details. + var hash uint32 = 9103 + + // Hash methods. + for i, n := 0, t.NumMethods(); i < n; i++ { + // Method order is not significant. + // Ignore m.Pkg(). + m := t.Method(i) + // Use shallow hash on method signature to + // avoid anonymous interface cycles. + hash += 3*hashString(m.Name()) + 5*h.shallowHash(m.Type()) + } + + // Hash type restrictions. + terms, err := typeparams.InterfaceTermSet(t) + // if err != nil t has invalid type restrictions. + if err == nil { + hash += h.hashTermSet(terms) + } + + return hash + + case *types.Map: + return 9109 + 2*h.hash(t.Key()) + 3*h.hash(t.Elem()) + + case *types.Chan: + return 9127 + 2*uint32(t.Dir()) + 3*h.hash(t.Elem()) + + case *types.Named: + hash := h.hashTypeName(t.Obj()) + targs := t.TypeArgs() + for i := 0; i < targs.Len(); i++ { + targ := targs.At(i) + hash += 2 * h.hash(targ) + } + return hash + + case *types.TypeParam: + return h.hashTypeParam(t) + + case *types.Tuple: + return h.hashTuple(t) + } + + panic(fmt.Sprintf("%T: %v", t, t)) +} + +func (h hasher) hashTuple(tuple *types.Tuple) uint32 { + // See go/types.identicalTypes for rationale. + n := tuple.Len() + hash := 9137 + 2*uint32(n) + for i := range n { + hash += 3 * h.hash(tuple.At(i).Type()) + } + return hash +} + +func (h hasher) hashUnion(t *types.Union) uint32 { + // Hash type restrictions. + terms, err := typeparams.UnionTermSet(t) + // if err != nil t has invalid type restrictions. Fall back on a non-zero + // hash. + if err != nil { + return 9151 + } + return h.hashTermSet(terms) +} + +func (h hasher) hashTermSet(terms []*types.Term) uint32 { + hash := 9157 + 2*uint32(len(terms)) + for _, term := range terms { + // term order is not significant. + termHash := h.hash(term.Type()) + if term.Tilde() { + termHash *= 9161 + } + hash += 3 * termHash + } + return hash +} + +// hashTypeParam returns the hash of a type parameter. +func (h hasher) hashTypeParam(t *types.TypeParam) uint32 { + // Within the signature of a generic function, TypeParams are + // identical if they have the same index and constraint, so we + // hash them based on index. + // + // When we are outside a generic function, free TypeParams are + // identical iff they are the same object, so we can use a + // more discriminating hash consistent with object identity. + // This optimization saves [Map] about 4% when hashing all the + // types.Info.Types in the forward closure of net/http. + if !h.inGenericSig { + // Optimization: outside a generic function signature, + // use a more discrimating hash consistent with object identity. + return h.hashTypeName(t.Obj()) + } + return 9173 + 3*uint32(t.Index()) +} + +var theSeed = maphash.MakeSeed() + +// hashTypeName hashes the pointer of tname. +func (hasher) hashTypeName(tname *types.TypeName) uint32 { + // Since types.Identical uses == to compare TypeNames, + // the Hash function uses maphash.Comparable. + // TODO(adonovan): or will, when it becomes available in go1.24. + // In the meantime we use the pointer's numeric value. + // + // hash := maphash.Comparable(theSeed, tname) + // + // (Another approach would be to hash the name and package + // path, and whether or not it is a package-level typename. It + // is rare for a package to define multiple local types with + // the same name.) + hash := uintptr(unsafe.Pointer(tname)) + return uint32(hash ^ (hash >> 32)) +} + +// shallowHash computes a hash of t without looking at any of its +// element Types, to avoid potential anonymous cycles in the types of +// interface methods. +// +// When an unnamed non-empty interface type appears anywhere among the +// arguments or results of an interface method, there is a potential +// for endless recursion. Consider: +// +// type X interface { m() []*interface { X } } +// +// The problem is that the Methods of the interface in m's result type +// include m itself; there is no mention of the named type X that +// might help us break the cycle. +// (See comment in go/types.identical, case *Interface, for more.) +func (h hasher) shallowHash(t types.Type) uint32 { + // t is the type of an interface method (Signature), + // its params or results (Tuples), or their immediate + // elements (mostly Slice, Pointer, Basic, Named), + // so there's no need to optimize anything else. + switch t := t.(type) { + case *types.Alias: + return h.shallowHash(types.Unalias(t)) + + case *types.Signature: + var hash uint32 = 604171 + if t.Variadic() { + hash *= 971767 + } + // The Signature/Tuple recursion is always finite + // and invariably shallow. + return hash + 1062599*h.shallowHash(t.Params()) + 1282529*h.shallowHash(t.Results()) + + case *types.Tuple: + n := t.Len() + hash := 9137 + 2*uint32(n) + for i := range n { + hash += 53471161 * h.shallowHash(t.At(i).Type()) + } + return hash + + case *types.Basic: + return 45212177 * uint32(t.Kind()) + + case *types.Array: + return 1524181 + 2*uint32(t.Len()) + + case *types.Slice: + return 2690201 + + case *types.Struct: + return 3326489 + + case *types.Pointer: + return 4393139 + + case *types.Union: + return 562448657 + + case *types.Interface: + return 2124679 // no recursion here + + case *types.Map: + return 9109 + + case *types.Chan: + return 9127 + + case *types.Named: + return h.hashTypeName(t.Obj()) + + case *types.TypeParam: + return h.hashTypeParam(t) + } + panic(fmt.Sprintf("shallowHash: %T: %v", t, t)) +} diff --git a/vendor/golang.org/x/tools/go/types/typeutil/methodsetcache.go b/vendor/golang.org/x/tools/go/types/typeutil/methodsetcache.go new file mode 100644 index 0000000000..f7666028fe --- /dev/null +++ b/vendor/golang.org/x/tools/go/types/typeutil/methodsetcache.go @@ -0,0 +1,71 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file implements a cache of method sets. + +package typeutil + +import ( + "go/types" + "sync" +) + +// A MethodSetCache records the method set of each type T for which +// MethodSet(T) is called so that repeat queries are fast. +// The zero value is a ready-to-use cache instance. +type MethodSetCache struct { + mu sync.Mutex + named map[*types.Named]struct{ value, pointer *types.MethodSet } // method sets for named N and *N + others map[types.Type]*types.MethodSet // all other types +} + +// MethodSet returns the method set of type T. It is thread-safe. +// +// If cache is nil, this function is equivalent to types.NewMethodSet(T). +// Utility functions can thus expose an optional *MethodSetCache +// parameter to clients that care about performance. +func (cache *MethodSetCache) MethodSet(T types.Type) *types.MethodSet { + if cache == nil { + return types.NewMethodSet(T) + } + cache.mu.Lock() + defer cache.mu.Unlock() + + switch T := types.Unalias(T).(type) { + case *types.Named: + return cache.lookupNamed(T).value + + case *types.Pointer: + if N, ok := types.Unalias(T.Elem()).(*types.Named); ok { + return cache.lookupNamed(N).pointer + } + } + + // all other types + // (The map uses pointer equivalence, not type identity.) + mset := cache.others[T] + if mset == nil { + mset = types.NewMethodSet(T) + if cache.others == nil { + cache.others = make(map[types.Type]*types.MethodSet) + } + cache.others[T] = mset + } + return mset +} + +func (cache *MethodSetCache) lookupNamed(named *types.Named) struct{ value, pointer *types.MethodSet } { + if cache.named == nil { + cache.named = make(map[*types.Named]struct{ value, pointer *types.MethodSet }) + } + // Avoid recomputing mset(*T) for each distinct Pointer + // instance whose underlying type is a named type. + msets, ok := cache.named[named] + if !ok { + msets.value = types.NewMethodSet(named) + msets.pointer = types.NewMethodSet(types.NewPointer(named)) + cache.named[named] = msets + } + return msets +} diff --git a/vendor/golang.org/x/tools/go/types/typeutil/ui.go b/vendor/golang.org/x/tools/go/types/typeutil/ui.go new file mode 100644 index 0000000000..9dda6a25df --- /dev/null +++ b/vendor/golang.org/x/tools/go/types/typeutil/ui.go @@ -0,0 +1,53 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package typeutil + +// This file defines utilities for user interfaces that display types. + +import ( + "go/types" +) + +// IntuitiveMethodSet returns the intuitive method set of a type T, +// which is the set of methods you can call on an addressable value of +// that type. +// +// The result always contains MethodSet(T), and is exactly MethodSet(T) +// for interface types and for pointer-to-concrete types. +// For all other concrete types T, the result additionally +// contains each method belonging to *T if there is no identically +// named method on T itself. +// +// This corresponds to user intuition about method sets; +// this function is intended only for user interfaces. +// +// The order of the result is as for types.MethodSet(T). +func IntuitiveMethodSet(T types.Type, msets *MethodSetCache) []*types.Selection { + isPointerToConcrete := func(T types.Type) bool { + ptr, ok := types.Unalias(T).(*types.Pointer) + return ok && !types.IsInterface(ptr.Elem()) + } + + var result []*types.Selection + mset := msets.MethodSet(T) + if types.IsInterface(T) || isPointerToConcrete(T) { + for i, n := 0, mset.Len(); i < n; i++ { + result = append(result, mset.At(i)) + } + } else { + // T is some other concrete type. + // Report methods of T and *T, preferring those of T. + pmset := msets.MethodSet(types.NewPointer(T)) + for i, n := 0, pmset.Len(); i < n; i++ { + meth := pmset.At(i) + if m := mset.Lookup(meth.Obj().Pkg(), meth.Obj().Name()); m != nil { + meth = m + } + result = append(result, meth) + } + + } + return result +} diff --git a/vendor/golang.org/x/tools/internal/aliases/aliases.go b/vendor/golang.org/x/tools/internal/aliases/aliases.go index f7798e3354..b9425f5a20 100644 --- a/vendor/golang.org/x/tools/internal/aliases/aliases.go +++ b/vendor/golang.org/x/tools/internal/aliases/aliases.go @@ -28,7 +28,7 @@ import ( func NewAlias(enabled bool, pos token.Pos, pkg *types.Package, name string, rhs types.Type, tparams []*types.TypeParam) *types.TypeName { if enabled { tname := types.NewTypeName(pos, pkg, name, nil) - newAlias(tname, rhs, tparams) + SetTypeParams(types.NewAlias(tname, rhs), tparams) return tname } if len(tparams) > 0 { diff --git a/vendor/golang.org/x/tools/internal/aliases/aliases_go121.go b/vendor/golang.org/x/tools/internal/aliases/aliases_go121.go deleted file mode 100644 index a775fcc4be..0000000000 --- a/vendor/golang.org/x/tools/internal/aliases/aliases_go121.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2024 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.22 -// +build !go1.22 - -package aliases - -import ( - "go/types" -) - -// Alias is a placeholder for a go/types.Alias for <=1.21. -// It will never be created by go/types. -type Alias struct{} - -func (*Alias) String() string { panic("unreachable") } -func (*Alias) Underlying() types.Type { panic("unreachable") } -func (*Alias) Obj() *types.TypeName { panic("unreachable") } -func Rhs(alias *Alias) types.Type { panic("unreachable") } -func TypeParams(alias *Alias) *types.TypeParamList { panic("unreachable") } -func SetTypeParams(alias *Alias, tparams []*types.TypeParam) { panic("unreachable") } -func TypeArgs(alias *Alias) *types.TypeList { panic("unreachable") } -func Origin(alias *Alias) *Alias { panic("unreachable") } - -// Unalias returns the type t for go <=1.21. -func Unalias(t types.Type) types.Type { return t } - -func newAlias(name *types.TypeName, rhs types.Type, tparams []*types.TypeParam) *Alias { - panic("unreachable") -} - -// Enabled reports whether [NewAlias] should create [types.Alias] types. -// -// Before go1.22, this function always returns false. -func Enabled() bool { return false } diff --git a/vendor/golang.org/x/tools/internal/aliases/aliases_go122.go b/vendor/golang.org/x/tools/internal/aliases/aliases_go122.go index 31c159e42e..7716a3331d 100644 --- a/vendor/golang.org/x/tools/internal/aliases/aliases_go122.go +++ b/vendor/golang.org/x/tools/internal/aliases/aliases_go122.go @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.22 -// +build go1.22 - package aliases import ( @@ -14,22 +11,19 @@ import ( "go/types" ) -// Alias is an alias of types.Alias. -type Alias = types.Alias - // Rhs returns the type on the right-hand side of the alias declaration. -func Rhs(alias *Alias) types.Type { +func Rhs(alias *types.Alias) types.Type { if alias, ok := any(alias).(interface{ Rhs() types.Type }); ok { return alias.Rhs() // go1.23+ } // go1.22's Alias didn't have the Rhs method, // so Unalias is the best we can do. - return Unalias(alias) + return types.Unalias(alias) } // TypeParams returns the type parameter list of the alias. -func TypeParams(alias *Alias) *types.TypeParamList { +func TypeParams(alias *types.Alias) *types.TypeParamList { if alias, ok := any(alias).(interface{ TypeParams() *types.TypeParamList }); ok { return alias.TypeParams() // go1.23+ } @@ -37,7 +31,7 @@ func TypeParams(alias *Alias) *types.TypeParamList { } // SetTypeParams sets the type parameters of the alias type. -func SetTypeParams(alias *Alias, tparams []*types.TypeParam) { +func SetTypeParams(alias *types.Alias, tparams []*types.TypeParam) { if alias, ok := any(alias).(interface { SetTypeParams(tparams []*types.TypeParam) }); ok { @@ -48,7 +42,7 @@ func SetTypeParams(alias *Alias, tparams []*types.TypeParam) { } // TypeArgs returns the type arguments used to instantiate the Alias type. -func TypeArgs(alias *Alias) *types.TypeList { +func TypeArgs(alias *types.Alias) *types.TypeList { if alias, ok := any(alias).(interface{ TypeArgs() *types.TypeList }); ok { return alias.TypeArgs() // go1.23+ } @@ -57,25 +51,13 @@ func TypeArgs(alias *Alias) *types.TypeList { // Origin returns the generic Alias type of which alias is an instance. // If alias is not an instance of a generic alias, Origin returns alias. -func Origin(alias *Alias) *Alias { +func Origin(alias *types.Alias) *types.Alias { if alias, ok := any(alias).(interface{ Origin() *types.Alias }); ok { return alias.Origin() // go1.23+ } return alias // not an instance of a generic alias (go1.22) } -// Unalias is a wrapper of types.Unalias. -func Unalias(t types.Type) types.Type { return types.Unalias(t) } - -// newAlias is an internal alias around types.NewAlias. -// Direct usage is discouraged as the moment. -// Try to use NewAlias instead. -func newAlias(tname *types.TypeName, rhs types.Type, tparams []*types.TypeParam) *Alias { - a := types.NewAlias(tname, rhs) - SetTypeParams(a, tparams) - return a -} - // Enabled reports whether [NewAlias] should create [types.Alias] types. // // This function is expensive! Call it sparingly. @@ -91,7 +73,7 @@ func Enabled() bool { // many tests. Therefore any attempt to cache the result // is just incorrect. fset := token.NewFileSet() - f, _ := parser.ParseFile(fset, "a.go", "package p; type A = int", 0) + f, _ := parser.ParseFile(fset, "a.go", "package p; type A = int", parser.SkipObjectResolution) pkg, _ := new(types.Config).Check("p", fset, []*ast.File{f}, nil) _, enabled := pkg.Scope().Lookup("A").Type().(*types.Alias) return enabled diff --git a/vendor/golang.org/x/tools/internal/gcimporter/bimport.go b/vendor/golang.org/x/tools/internal/gcimporter/bimport.go index d98b0db2a9..d79a605ed1 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/bimport.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/bimport.go @@ -87,64 +87,3 @@ func chanDir(d int) types.ChanDir { return 0 } } - -var predeclOnce sync.Once -var predecl []types.Type // initialized lazily - -func predeclared() []types.Type { - predeclOnce.Do(func() { - // initialize lazily to be sure that all - // elements have been initialized before - predecl = []types.Type{ // basic types - types.Typ[types.Bool], - types.Typ[types.Int], - types.Typ[types.Int8], - types.Typ[types.Int16], - types.Typ[types.Int32], - types.Typ[types.Int64], - types.Typ[types.Uint], - types.Typ[types.Uint8], - types.Typ[types.Uint16], - types.Typ[types.Uint32], - types.Typ[types.Uint64], - types.Typ[types.Uintptr], - types.Typ[types.Float32], - types.Typ[types.Float64], - types.Typ[types.Complex64], - types.Typ[types.Complex128], - types.Typ[types.String], - - // basic type aliases - types.Universe.Lookup("byte").Type(), - types.Universe.Lookup("rune").Type(), - - // error - types.Universe.Lookup("error").Type(), - - // untyped types - types.Typ[types.UntypedBool], - types.Typ[types.UntypedInt], - types.Typ[types.UntypedRune], - types.Typ[types.UntypedFloat], - types.Typ[types.UntypedComplex], - types.Typ[types.UntypedString], - types.Typ[types.UntypedNil], - - // package unsafe - types.Typ[types.UnsafePointer], - - // invalid type - types.Typ[types.Invalid], // only appears in packages with errors - - // used internally by gc; never used by this package or in .a files - anyType{}, - } - predecl = append(predecl, additionalPredeclared()...) - }) - return predecl -} - -type anyType struct{} - -func (t anyType) Underlying() types.Type { return t } -func (t anyType) String() string { return "any" } diff --git a/vendor/golang.org/x/tools/internal/gcimporter/exportdata.go b/vendor/golang.org/x/tools/internal/gcimporter/exportdata.go index f6437feb1c..5662a311da 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/exportdata.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/exportdata.go @@ -2,49 +2,183 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// This file is a copy of $GOROOT/src/go/internal/gcimporter/exportdata.go. - -// This file implements FindExportData. +// This file should be kept in sync with $GOROOT/src/internal/exportdata/exportdata.go. +// This file also additionally implements FindExportData for gcexportdata.NewReader. package gcimporter import ( "bufio" + "bytes" + "errors" "fmt" + "go/build" "io" - "strconv" + "os" + "os/exec" + "path/filepath" "strings" + "sync" ) -func readGopackHeader(r *bufio.Reader) (name string, size int64, err error) { - // See $GOROOT/include/ar.h. - hdr := make([]byte, 16+12+6+6+8+10+2) - _, err = io.ReadFull(r, hdr) +// FindExportData positions the reader r at the beginning of the +// export data section of an underlying cmd/compile created archive +// file by reading from it. The reader must be positioned at the +// start of the file before calling this function. +// This returns the length of the export data in bytes. +// +// This function is needed by [gcexportdata.Read], which must +// accept inputs produced by the last two releases of cmd/compile, +// plus tip. +func FindExportData(r *bufio.Reader) (size int64, err error) { + arsize, err := FindPackageDefinition(r) + if err != nil { + return + } + size = int64(arsize) + + objapi, headers, err := ReadObjectHeaders(r) if err != nil { return } - // leave for debugging - if false { - fmt.Printf("header: %s", hdr) + size -= int64(len(objapi)) + for _, h := range headers { + size -= int64(len(h)) + } + + // Check for the binary export data section header "$$B\n". + // TODO(taking): Unify with ReadExportDataHeader so that it stops at the 'u' instead of reading + line, err := r.ReadSlice('\n') + if err != nil { + return + } + hdr := string(line) + if hdr != "$$B\n" { + err = fmt.Errorf("unknown export data header: %q", hdr) + return } - s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10])) - length, err := strconv.Atoi(s) - size = int64(length) - if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' { - err = fmt.Errorf("invalid archive header") + size -= int64(len(hdr)) + + // For files with a binary export data header "$$B\n", + // these are always terminated by an end-of-section marker "\n$$\n". + // So the last bytes must always be this constant. + // + // The end-of-section marker is not a part of the export data itself. + // Do not include these in size. + // + // It would be nice to have sanity check that the final bytes after + // the export data are indeed the end-of-section marker. The split + // of gcexportdata.NewReader and gcexportdata.Read make checking this + // ugly so gcimporter gives up enforcing this. The compiler and go/types + // importer do enforce this, which seems good enough. + const endofsection = "\n$$\n" + size -= int64(len(endofsection)) + + if size < 0 { + err = fmt.Errorf("invalid size (%d) in the archive file: %d bytes remain without section headers (recompile package)", arsize, size) return } - name = strings.TrimSpace(string(hdr[:16])) + return } -// FindExportData positions the reader r at the beginning of the -// export data section of an underlying GC-created object/archive -// file by reading from it. The reader must be positioned at the -// start of the file before calling this function. The hdr result -// is the string before the export data, either "$$" or "$$B". -// The size result is the length of the export data in bytes, or -1 if not known. -func FindExportData(r *bufio.Reader) (hdr string, size int64, err error) { +// ReadUnified reads the contents of the unified export data from a reader r +// that contains the contents of a GC-created archive file. +// +// On success, the reader will be positioned after the end-of-section marker "\n$$\n". +// +// Supported GC-created archive files have 4 layers of nesting: +// - An archive file containing a package definition file. +// - The package definition file contains headers followed by a data section. +// Headers are lines (≤ 4kb) that do not start with "$$". +// - The data section starts with "$$B\n" followed by export data followed +// by an end of section marker "\n$$\n". (The section start "$$\n" is no +// longer supported.) +// - The export data starts with a format byte ('u') followed by the in +// the given format. (See ReadExportDataHeader for older formats.) +// +// Putting this together, the bytes in a GC-created archive files are expected +// to look like the following. +// See cmd/internal/archive for more details on ar file headers. +// +// | \n | ar file signature +// | __.PKGDEF...size...\n | ar header for __.PKGDEF including size. +// | go object <...>\n | objabi header +// | \n | other headers such as build id +// | $$B\n | binary format marker +// | u\n | unified export +// | $$\n | end-of-section marker +// | [optional padding] | padding byte (0x0A) if size is odd +// | [ar file header] | other ar files +// | [ar file data] | +func ReadUnified(r *bufio.Reader) (data []byte, err error) { + // We historically guaranteed headers at the default buffer size (4096) work. + // This ensures we can use ReadSlice throughout. + const minBufferSize = 4096 + r = bufio.NewReaderSize(r, minBufferSize) + + size, err := FindPackageDefinition(r) + if err != nil { + return + } + n := size + + objapi, headers, err := ReadObjectHeaders(r) + if err != nil { + return + } + n -= len(objapi) + for _, h := range headers { + n -= len(h) + } + + hdrlen, err := ReadExportDataHeader(r) + if err != nil { + return + } + n -= hdrlen + + // size also includes the end of section marker. Remove that many bytes from the end. + const marker = "\n$$\n" + n -= len(marker) + + if n < 0 { + err = fmt.Errorf("invalid size (%d) in the archive file: %d bytes remain without section headers (recompile package)", size, n) + return + } + + // Read n bytes from buf. + data = make([]byte, n) + _, err = io.ReadFull(r, data) + if err != nil { + return + } + + // Check for marker at the end. + var suffix [len(marker)]byte + _, err = io.ReadFull(r, suffix[:]) + if err != nil { + return + } + if s := string(suffix[:]); s != marker { + err = fmt.Errorf("read %q instead of end-of-section marker (%q)", s, marker) + return + } + + return +} + +// FindPackageDefinition positions the reader r at the beginning of a package +// definition file ("__.PKGDEF") within a GC-created archive by reading +// from it, and returns the size of the package definition file in the archive. +// +// The reader must be positioned at the start of the archive file before calling +// this function, and "__.PKGDEF" is assumed to be the first file in the archive. +// +// See cmd/internal/archive for details on the archive format. +func FindPackageDefinition(r *bufio.Reader) (size int, err error) { + // Uses ReadSlice to limit risk of malformed inputs. + // Read first line to make sure this is an object file. line, err := r.ReadSlice('\n') if err != nil { @@ -52,48 +186,236 @@ func FindExportData(r *bufio.Reader) (hdr string, size int64, err error) { return } - if string(line) == "!\n" { - // Archive file. Scan to __.PKGDEF. - var name string - if name, size, err = readGopackHeader(r); err != nil { - return - } + // Is the first line an archive file signature? + if string(line) != "!\n" { + err = fmt.Errorf("not the start of an archive file (%q)", line) + return + } + + // package export block should be first + size = readArchiveHeader(r, "__.PKGDEF") + if size <= 0 { + err = fmt.Errorf("not a package file") + return + } + + return +} - // First entry should be __.PKGDEF. - if name != "__.PKGDEF" { - err = fmt.Errorf("go archive is missing __.PKGDEF") +// ReadObjectHeaders reads object headers from the reader. Object headers are +// lines that do not start with an end-of-section marker "$$". The first header +// is the objabi header. On success, the reader will be positioned at the beginning +// of the end-of-section marker. +// +// It returns an error if any header does not fit in r.Size() bytes. +func ReadObjectHeaders(r *bufio.Reader) (objapi string, headers []string, err error) { + // line is a temporary buffer for headers. + // Use bounded reads (ReadSlice, Peek) to limit risk of malformed inputs. + var line []byte + + // objapi header should be the first line + if line, err = r.ReadSlice('\n'); err != nil { + err = fmt.Errorf("can't find export data (%v)", err) + return + } + objapi = string(line) + + // objapi header begins with "go object ". + if !strings.HasPrefix(objapi, "go object ") { + err = fmt.Errorf("not a go object file: %s", objapi) + return + } + + // process remaining object header lines + for { + // check for an end of section marker "$$" + line, err = r.Peek(2) + if err != nil { return } + if string(line) == "$$" { + return // stop + } - // Read first line of __.PKGDEF data, so that line - // is once again the first line of the input. - if line, err = r.ReadSlice('\n'); err != nil { - err = fmt.Errorf("can't find export data (%v)", err) + // read next header + line, err = r.ReadSlice('\n') + if err != nil { return } - size -= int64(len(line)) + headers = append(headers, string(line)) } +} - // Now at __.PKGDEF in archive or still at beginning of file. - // Either way, line should begin with "go object ". - if !strings.HasPrefix(string(line), "go object ") { - err = fmt.Errorf("not a Go object file") +// ReadExportDataHeader reads the export data header and format from r. +// It returns the number of bytes read, or an error if the format is no longer +// supported or it failed to read. +// +// The only currently supported format is binary export data in the +// unified export format. +func ReadExportDataHeader(r *bufio.Reader) (n int, err error) { + // Read export data header. + line, err := r.ReadSlice('\n') + if err != nil { return } - // Skip over object header to export data. - // Begins after first line starting with $$. - for line[0] != '$' { - if line, err = r.ReadSlice('\n'); err != nil { - err = fmt.Errorf("can't find export data (%v)", err) + hdr := string(line) + switch hdr { + case "$$\n": + err = fmt.Errorf("old textual export format no longer supported (recompile package)") + return + + case "$$B\n": + var format byte + format, err = r.ReadByte() + if err != nil { return } - size -= int64(len(line)) - } - hdr = string(line) - if size < 0 { - size = -1 + // The unified export format starts with a 'u'. + switch format { + case 'u': + default: + // Older no longer supported export formats include: + // indexed export format which started with an 'i'; and + // the older binary export format which started with a 'c', + // 'd', or 'v' (from "version"). + err = fmt.Errorf("binary export format %q is no longer supported (recompile package)", format) + return + } + + default: + err = fmt.Errorf("unknown export data header: %q", hdr) + return } + n = len(hdr) + 1 // + 1 is for 'u' return } + +// FindPkg returns the filename and unique package id for an import +// path based on package information provided by build.Import (using +// the build.Default build.Context). A relative srcDir is interpreted +// relative to the current working directory. +// +// FindPkg is only used in tests within x/tools. +func FindPkg(path, srcDir string) (filename, id string, err error) { + // TODO(taking): Move internal/exportdata.FindPkg into its own file, + // and then this copy into a _test package. + if path == "" { + return "", "", errors.New("path is empty") + } + + var noext string + switch { + default: + // "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x" + // Don't require the source files to be present. + if abs, err := filepath.Abs(srcDir); err == nil { // see issue 14282 + srcDir = abs + } + var bp *build.Package + bp, err = build.Import(path, srcDir, build.FindOnly|build.AllowBinary) + if bp.PkgObj == "" { + if bp.Goroot && bp.Dir != "" { + filename, err = lookupGorootExport(bp.Dir) + if err == nil { + _, err = os.Stat(filename) + } + if err == nil { + return filename, bp.ImportPath, nil + } + } + goto notfound + } else { + noext = strings.TrimSuffix(bp.PkgObj, ".a") + } + id = bp.ImportPath + + case build.IsLocalImport(path): + // "./x" -> "/this/directory/x.ext", "/this/directory/x" + noext = filepath.Join(srcDir, path) + id = noext + + case filepath.IsAbs(path): + // for completeness only - go/build.Import + // does not support absolute imports + // "/x" -> "/x.ext", "/x" + noext = path + id = path + } + + if false { // for debugging + if path != id { + fmt.Printf("%s -> %s\n", path, id) + } + } + + // try extensions + for _, ext := range pkgExts { + filename = noext + ext + f, statErr := os.Stat(filename) + if statErr == nil && !f.IsDir() { + return filename, id, nil + } + if err == nil { + err = statErr + } + } + +notfound: + if err == nil { + return "", path, fmt.Errorf("can't find import: %q", path) + } + return "", path, fmt.Errorf("can't find import: %q: %w", path, err) +} + +var pkgExts = [...]string{".a", ".o"} // a file from the build cache will have no extension + +var exportMap sync.Map // package dir → func() (string, error) + +// lookupGorootExport returns the location of the export data +// (normally found in the build cache, but located in GOROOT/pkg +// in prior Go releases) for the package located in pkgDir. +// +// (We use the package's directory instead of its import path +// mainly to simplify handling of the packages in src/vendor +// and cmd/vendor.) +// +// lookupGorootExport is only used in tests within x/tools. +func lookupGorootExport(pkgDir string) (string, error) { + f, ok := exportMap.Load(pkgDir) + if !ok { + var ( + listOnce sync.Once + exportPath string + err error + ) + f, _ = exportMap.LoadOrStore(pkgDir, func() (string, error) { + listOnce.Do(func() { + cmd := exec.Command(filepath.Join(build.Default.GOROOT, "bin", "go"), "list", "-export", "-f", "{{.Export}}", pkgDir) + cmd.Dir = build.Default.GOROOT + cmd.Env = append(os.Environ(), "PWD="+cmd.Dir, "GOROOT="+build.Default.GOROOT) + var output []byte + output, err = cmd.Output() + if err != nil { + if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 { + err = errors.New(string(ee.Stderr)) + } + return + } + + exports := strings.Split(string(bytes.TrimSpace(output)), "\n") + if len(exports) != 1 { + err = fmt.Errorf("go list reported %d exports; expected 1", len(exports)) + return + } + + exportPath = exports[0] + }) + + return exportPath, err + }) + } + + return f.(func() (string, error))() +} diff --git a/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go b/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go index 39df91124a..3dbd21d1b9 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go @@ -23,17 +23,11 @@ package gcimporter // import "golang.org/x/tools/internal/gcimporter" import ( "bufio" - "bytes" "fmt" - "go/build" "go/token" "go/types" "io" "os" - "os/exec" - "path/filepath" - "strings" - "sync" ) const ( @@ -45,125 +39,14 @@ const ( trace = false ) -var exportMap sync.Map // package dir → func() (string, bool) - -// lookupGorootExport returns the location of the export data -// (normally found in the build cache, but located in GOROOT/pkg -// in prior Go releases) for the package located in pkgDir. -// -// (We use the package's directory instead of its import path -// mainly to simplify handling of the packages in src/vendor -// and cmd/vendor.) -func lookupGorootExport(pkgDir string) (string, bool) { - f, ok := exportMap.Load(pkgDir) - if !ok { - var ( - listOnce sync.Once - exportPath string - ) - f, _ = exportMap.LoadOrStore(pkgDir, func() (string, bool) { - listOnce.Do(func() { - cmd := exec.Command("go", "list", "-export", "-f", "{{.Export}}", pkgDir) - cmd.Dir = build.Default.GOROOT - var output []byte - output, err := cmd.Output() - if err != nil { - return - } - - exports := strings.Split(string(bytes.TrimSpace(output)), "\n") - if len(exports) != 1 { - return - } - - exportPath = exports[0] - }) - - return exportPath, exportPath != "" - }) - } - - return f.(func() (string, bool))() -} - -var pkgExts = [...]string{".a", ".o"} - -// FindPkg returns the filename and unique package id for an import -// path based on package information provided by build.Import (using -// the build.Default build.Context). A relative srcDir is interpreted -// relative to the current working directory. -// If no file was found, an empty filename is returned. -func FindPkg(path, srcDir string) (filename, id string) { - if path == "" { - return - } - - var noext string - switch { - default: - // "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x" - // Don't require the source files to be present. - if abs, err := filepath.Abs(srcDir); err == nil { // see issue 14282 - srcDir = abs - } - bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary) - if bp.PkgObj == "" { - var ok bool - if bp.Goroot && bp.Dir != "" { - filename, ok = lookupGorootExport(bp.Dir) - } - if !ok { - id = path // make sure we have an id to print in error message - return - } - } else { - noext = strings.TrimSuffix(bp.PkgObj, ".a") - id = bp.ImportPath - } - - case build.IsLocalImport(path): - // "./x" -> "/this/directory/x.ext", "/this/directory/x" - noext = filepath.Join(srcDir, path) - id = noext - - case filepath.IsAbs(path): - // for completeness only - go/build.Import - // does not support absolute imports - // "/x" -> "/x.ext", "/x" - noext = path - id = path - } - - if false { // for debugging - if path != id { - fmt.Printf("%s -> %s\n", path, id) - } - } - - if filename != "" { - if f, err := os.Stat(filename); err == nil && !f.IsDir() { - return - } - } - - // try extensions - for _, ext := range pkgExts { - filename = noext + ext - if f, err := os.Stat(filename); err == nil && !f.IsDir() { - return - } - } - - filename = "" // not found - return -} - // Import imports a gc-generated package given its import path and srcDir, adds // the corresponding package object to the packages map, and returns the object. // The packages map must contain all packages already imported. -func Import(packages map[string]*types.Package, path, srcDir string, lookup func(path string) (io.ReadCloser, error)) (pkg *types.Package, err error) { +// +// Import is only used in tests. +func Import(fset *token.FileSet, packages map[string]*types.Package, path, srcDir string, lookup func(path string) (io.ReadCloser, error)) (pkg *types.Package, err error) { var rc io.ReadCloser - var filename, id string + var id string if lookup != nil { // With custom lookup specified, assume that caller has // converted path to a canonical import path for use in the map. @@ -182,12 +65,13 @@ func Import(packages map[string]*types.Package, path, srcDir string, lookup func } rc = f } else { - filename, id = FindPkg(path, srcDir) + var filename string + filename, id, err = FindPkg(path, srcDir) if filename == "" { if path == "unsafe" { return types.Unsafe, nil } - return nil, fmt.Errorf("can't find import: %q", id) + return nil, err } // no need to re-import if the package was imported completely before @@ -210,57 +94,15 @@ func Import(packages map[string]*types.Package, path, srcDir string, lookup func } defer rc.Close() - var hdr string - var size int64 buf := bufio.NewReader(rc) - if hdr, size, err = FindExportData(buf); err != nil { + data, err := ReadUnified(buf) + if err != nil { + err = fmt.Errorf("import %q: %v", path, err) return } - switch hdr { - case "$$B\n": - var data []byte - data, err = io.ReadAll(buf) - if err != nil { - break - } - - // TODO(gri): allow clients of go/importer to provide a FileSet. - // Or, define a new standard go/types/gcexportdata package. - fset := token.NewFileSet() - - // Select appropriate importer. - if len(data) > 0 { - switch data[0] { - case 'v', 'c', 'd': // binary, till go1.10 - return nil, fmt.Errorf("binary (%c) import format is no longer supported", data[0]) - - case 'i': // indexed, till go1.19 - _, pkg, err := IImportData(fset, packages, data[1:], id) - return pkg, err - - case 'u': // unified, from go1.20 - _, pkg, err := UImportData(fset, packages, data[1:size], id) - return pkg, err - - default: - l := len(data) - if l > 10 { - l = 10 - } - return nil, fmt.Errorf("unexpected export data with prefix %q for path %s", string(data[:l]), id) - } - } - - default: - err = fmt.Errorf("unknown export data header: %q", hdr) - } + // unified: emitted by cmd/compile since go1.20. + _, pkg, err = UImportData(fset, packages, data, id) return } - -type byPath []*types.Package - -func (a byPath) Len() int { return len(a) } -func (a byPath) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a byPath) Less(i, j int) bool { return a[i].Path() < a[j].Path() } diff --git a/vendor/golang.org/x/tools/internal/gcimporter/iexport.go b/vendor/golang.org/x/tools/internal/gcimporter/iexport.go index 5f283281a2..7dfc31a37d 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/iexport.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/iexport.go @@ -242,11 +242,30 @@ import ( "golang.org/x/tools/go/types/objectpath" "golang.org/x/tools/internal/aliases" - "golang.org/x/tools/internal/tokeninternal" ) // IExportShallow encodes "shallow" export data for the specified package. // +// For types, we use "shallow" export data. Historically, the Go +// compiler always produced a summary of the types for a given package +// that included types from other packages that it indirectly +// referenced: "deep" export data. This had the advantage that the +// compiler (and analogous tools such as gopls) need only load one +// file per direct import. However, it meant that the files tended to +// get larger based on the level of the package in the import +// graph. For example, higher-level packages in the kubernetes module +// have over 1MB of "deep" export data, even when they have almost no +// content of their own, merely because they mention a major type that +// references many others. In pathological cases the export data was +// 300x larger than the source for a package due to this quadratic +// growth. +// +// "Shallow" export data means that the serialized types describe only +// a single package. If those types mention types from other packages, +// the type checker may need to request additional packages beyond +// just the direct imports. Type information for the entire transitive +// closure of imports is provided (lazily) by the DAG. +// // No promises are made about the encoding other than that it can be decoded by // the same version of IIExportShallow. If you plan to save export data in the // file system, be sure to include a cryptographic digest of the executable in @@ -269,8 +288,8 @@ func IExportShallow(fset *token.FileSet, pkg *types.Package, reportf ReportFunc) } // IImportShallow decodes "shallow" types.Package data encoded by -// IExportShallow in the same executable. This function cannot import data from -// cmd/compile or gcexportdata.Write. +// [IExportShallow] in the same executable. This function cannot import data +// from cmd/compile or gcexportdata.Write. // // The importer calls getPackages to obtain package symbols for all // packages mentioned in the export data, including the one being @@ -441,7 +460,7 @@ func (p *iexporter) encodeFile(w *intWriter, file *token.File, needed []uint64) // Sort the set of needed offsets. Duplicates are harmless. sort.Slice(needed, func(i, j int) bool { return needed[i] < needed[j] }) - lines := tokeninternal.GetLines(file) // byte offset of each line start + lines := file.Lines() // byte offset of each line start w.uint64(uint64(len(lines))) // Rather than record the entire array of line start offsets, @@ -725,13 +744,13 @@ func (p *iexporter) doDecl(obj types.Object) { case *types.TypeName: t := obj.Type() - if tparam, ok := aliases.Unalias(t).(*types.TypeParam); ok { + if tparam, ok := types.Unalias(t).(*types.TypeParam); ok { w.tag(typeParamTag) w.pos(obj.Pos()) constraint := tparam.Constraint() if p.version >= iexportVersionGo1_18 { implicit := false - if iface, _ := aliases.Unalias(constraint).(*types.Interface); iface != nil { + if iface, _ := types.Unalias(constraint).(*types.Interface); iface != nil { implicit = iface.IsImplicit() } w.bool(implicit) @@ -741,7 +760,7 @@ func (p *iexporter) doDecl(obj types.Object) { } if obj.IsAlias() { - alias, materialized := t.(*aliases.Alias) // may fail when aliases are not enabled + alias, materialized := t.(*types.Alias) // may fail when aliases are not enabled var tparams *types.TypeParamList if materialized { @@ -975,7 +994,7 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) { }() } switch t := t.(type) { - case *aliases.Alias: + case *types.Alias: if targs := aliases.TypeArgs(t); targs.Len() > 0 { w.startType(instanceType) w.pos(t.Obj().Pos()) @@ -1091,7 +1110,7 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) { for i := 0; i < n; i++ { ft := t.EmbeddedType(i) tPkg := pkg - if named, _ := aliases.Unalias(ft).(*types.Named); named != nil { + if named, _ := types.Unalias(ft).(*types.Named); named != nil { w.pos(named.Obj().Pos()) } else { w.pos(token.NoPos) diff --git a/vendor/golang.org/x/tools/internal/gcimporter/iimport.go b/vendor/golang.org/x/tools/internal/gcimporter/iimport.go index ed2d562959..1294392715 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/iimport.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/iimport.go @@ -5,8 +5,6 @@ // Indexed package import. // See iexport.go for the export data format. -// This file is a copy of $GOROOT/src/go/internal/gcimporter/iimport.go. - package gcimporter import ( @@ -53,6 +51,7 @@ const ( iexportVersionPosCol = 1 iexportVersionGo1_18 = 2 iexportVersionGenerics = 2 + iexportVersion = iexportVersionGenerics iexportVersionCurrent = 2 ) @@ -540,7 +539,7 @@ func canReuse(def *types.Named, rhs types.Type) bool { if def == nil { return true } - iface, _ := aliases.Unalias(rhs).(*types.Interface) + iface, _ := types.Unalias(rhs).(*types.Interface) if iface == nil { return true } @@ -557,6 +556,14 @@ type importReader struct { prevColumn int64 } +// markBlack is redefined in iimport_go123.go, to work around golang/go#69912. +// +// If TypeNames are not marked black (in the sense of go/types cycle +// detection), they may be mutated when dot-imported. Fix this by punching a +// hole through the type, when compiling with Go 1.23. (The bug has been fixed +// for 1.24, but the fix was not worth back-porting). +var markBlack = func(name *types.TypeName) {} + func (r *importReader) obj(name string) { tag := r.byte() pos := r.pos() @@ -569,6 +576,7 @@ func (r *importReader) obj(name string) { } typ := r.typ() obj := aliases.NewAlias(r.p.aliases, pos, r.currPkg, name, typ, tparams) + markBlack(obj) // workaround for golang/go#69912 r.declare(obj) case constTag: @@ -589,6 +597,9 @@ func (r *importReader) obj(name string) { // declaration before recursing. obj := types.NewTypeName(pos, r.currPkg, name, nil) named := types.NewNamed(obj, nil, nil) + + markBlack(obj) // workaround for golang/go#69912 + // Declare obj before calling r.tparamList, so the new type name is recognized // if used in the constraint of one of its own typeparams (see #48280). r.declare(obj) @@ -615,7 +626,7 @@ func (r *importReader) obj(name string) { if targs.Len() > 0 { rparams = make([]*types.TypeParam, targs.Len()) for i := range rparams { - rparams[i] = aliases.Unalias(targs.At(i)).(*types.TypeParam) + rparams[i] = types.Unalias(targs.At(i)).(*types.TypeParam) } } msig := r.signature(recv, rparams, nil) @@ -645,7 +656,7 @@ func (r *importReader) obj(name string) { } constraint := r.typ() if implicit { - iface, _ := aliases.Unalias(constraint).(*types.Interface) + iface, _ := types.Unalias(constraint).(*types.Interface) if iface == nil { errorf("non-interface constraint marked implicit") } @@ -660,7 +671,9 @@ func (r *importReader) obj(name string) { case varTag: typ := r.typ() - r.declare(types.NewVar(pos, r.currPkg, name, typ)) + v := types.NewVar(pos, r.currPkg, name, typ) + typesinternal.SetVarKind(v, typesinternal.PackageVar) + r.declare(v) default: errorf("unexpected tag: %v", tag) @@ -852,7 +865,7 @@ func (r *importReader) typ() types.Type { } func isInterface(t types.Type) bool { - _, ok := aliases.Unalias(t).(*types.Interface) + _, ok := types.Unalias(t).(*types.Interface) return ok } @@ -959,7 +972,7 @@ func (r *importReader) doType(base *types.Named) (res types.Type) { methods[i] = method } - typ := newInterface(methods, embeddeds) + typ := types.NewInterfaceType(methods, embeddeds) r.p.interfaceList = append(r.p.interfaceList, typ) return typ @@ -1051,7 +1064,7 @@ func (r *importReader) tparamList() []*types.TypeParam { for i := range xs { // Note: the standard library importer is tolerant of nil types here, // though would panic in SetTypeParams. - xs[i] = aliases.Unalias(r.typ()).(*types.TypeParam) + xs[i] = types.Unalias(r.typ()).(*types.TypeParam) } return xs } @@ -1098,3 +1111,9 @@ func (r *importReader) byte() byte { } return x } + +type byPath []*types.Package + +func (a byPath) Len() int { return len(a) } +func (a byPath) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byPath) Less(i, j int) bool { return a[i].Path() < a[j].Path() } diff --git a/vendor/golang.org/x/tools/internal/gcimporter/iimport_go122.go b/vendor/golang.org/x/tools/internal/gcimporter/iimport_go122.go new file mode 100644 index 0000000000..7586bfaca6 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/gcimporter/iimport_go122.go @@ -0,0 +1,53 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.22 && !go1.24 + +package gcimporter + +import ( + "go/token" + "go/types" + "unsafe" +) + +// TODO(rfindley): delete this workaround once go1.24 is assured. + +func init() { + // Update markBlack so that it correctly sets the color + // of imported TypeNames. + // + // See the doc comment for markBlack for details. + + type color uint32 + const ( + white color = iota + black + grey + ) + type object struct { + _ *types.Scope + _ token.Pos + _ *types.Package + _ string + _ types.Type + _ uint32 + color_ color + _ token.Pos + } + type typeName struct { + object + } + + // If the size of types.TypeName changes, this will fail to compile. + const delta = int64(unsafe.Sizeof(typeName{})) - int64(unsafe.Sizeof(types.TypeName{})) + var _ [-delta * delta]int + + markBlack = func(obj *types.TypeName) { + type uP = unsafe.Pointer + var ptr *typeName + *(*uP)(uP(&ptr)) = uP(obj) + ptr.color_ = black + } +} diff --git a/vendor/golang.org/x/tools/internal/gcimporter/newInterface10.go b/vendor/golang.org/x/tools/internal/gcimporter/newInterface10.go deleted file mode 100644 index 8b163e3d05..0000000000 --- a/vendor/golang.org/x/tools/internal/gcimporter/newInterface10.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.11 -// +build !go1.11 - -package gcimporter - -import "go/types" - -func newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interface { - named := make([]*types.Named, len(embeddeds)) - for i, e := range embeddeds { - var ok bool - named[i], ok = e.(*types.Named) - if !ok { - panic("embedding of non-defined interfaces in interfaces is not supported before Go 1.11") - } - } - return types.NewInterface(methods, named) -} diff --git a/vendor/golang.org/x/tools/internal/gcimporter/newInterface11.go b/vendor/golang.org/x/tools/internal/gcimporter/newInterface11.go deleted file mode 100644 index 49984f40fd..0000000000 --- a/vendor/golang.org/x/tools/internal/gcimporter/newInterface11.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.11 -// +build go1.11 - -package gcimporter - -import "go/types" - -func newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interface { - return types.NewInterfaceType(methods, embeddeds) -} diff --git a/vendor/golang.org/x/tools/internal/gcimporter/predeclared.go b/vendor/golang.org/x/tools/internal/gcimporter/predeclared.go new file mode 100644 index 0000000000..907c8557a5 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/gcimporter/predeclared.go @@ -0,0 +1,91 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gcimporter + +import ( + "go/types" + "sync" +) + +// predecl is a cache for the predeclared types in types.Universe. +// +// Cache a distinct result based on the runtime value of any. +// The pointer value of the any type varies based on GODEBUG settings. +var predeclMu sync.Mutex +var predecl map[types.Type][]types.Type + +func predeclared() []types.Type { + anyt := types.Universe.Lookup("any").Type() + + predeclMu.Lock() + defer predeclMu.Unlock() + + if pre, ok := predecl[anyt]; ok { + return pre + } + + if predecl == nil { + predecl = make(map[types.Type][]types.Type) + } + + decls := []types.Type{ // basic types + types.Typ[types.Bool], + types.Typ[types.Int], + types.Typ[types.Int8], + types.Typ[types.Int16], + types.Typ[types.Int32], + types.Typ[types.Int64], + types.Typ[types.Uint], + types.Typ[types.Uint8], + types.Typ[types.Uint16], + types.Typ[types.Uint32], + types.Typ[types.Uint64], + types.Typ[types.Uintptr], + types.Typ[types.Float32], + types.Typ[types.Float64], + types.Typ[types.Complex64], + types.Typ[types.Complex128], + types.Typ[types.String], + + // basic type aliases + types.Universe.Lookup("byte").Type(), + types.Universe.Lookup("rune").Type(), + + // error + types.Universe.Lookup("error").Type(), + + // untyped types + types.Typ[types.UntypedBool], + types.Typ[types.UntypedInt], + types.Typ[types.UntypedRune], + types.Typ[types.UntypedFloat], + types.Typ[types.UntypedComplex], + types.Typ[types.UntypedString], + types.Typ[types.UntypedNil], + + // package unsafe + types.Typ[types.UnsafePointer], + + // invalid type + types.Typ[types.Invalid], // only appears in packages with errors + + // used internally by gc; never used by this package or in .a files + anyType{}, + + // comparable + types.Universe.Lookup("comparable").Type(), + + // any + anyt, + } + + predecl[anyt] = decls + return decls +} + +type anyType struct{} + +func (t anyType) Underlying() types.Type { return t } +func (t anyType) String() string { return "any" } diff --git a/vendor/golang.org/x/tools/internal/gcimporter/support.go b/vendor/golang.org/x/tools/internal/gcimporter/support.go new file mode 100644 index 0000000000..4af810dc41 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/gcimporter/support.go @@ -0,0 +1,30 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gcimporter + +import ( + "bufio" + "io" + "strconv" + "strings" +) + +// Copy of $GOROOT/src/cmd/internal/archive.ReadHeader. +func readArchiveHeader(b *bufio.Reader, name string) int { + // architecture-independent object file output + const HeaderSize = 60 + + var buf [HeaderSize]byte + if _, err := io.ReadFull(b, buf[:]); err != nil { + return -1 + } + aname := strings.Trim(string(buf[0:16]), " ") + if !strings.HasPrefix(aname, name) { + return -1 + } + asize := strings.Trim(string(buf[48:58]), " ") + i, _ := strconv.Atoi(asize) + return i +} diff --git a/vendor/golang.org/x/tools/internal/gcimporter/support_go118.go b/vendor/golang.org/x/tools/internal/gcimporter/support_go118.go deleted file mode 100644 index 0cd3b91b65..0000000000 --- a/vendor/golang.org/x/tools/internal/gcimporter/support_go118.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gcimporter - -import "go/types" - -const iexportVersion = iexportVersionGenerics - -// additionalPredeclared returns additional predeclared types in go.1.18. -func additionalPredeclared() []types.Type { - return []types.Type{ - // comparable - types.Universe.Lookup("comparable").Type(), - - // any - types.Universe.Lookup("any").Type(), - } -} - -// See cmd/compile/internal/types.SplitVargenSuffix. -func splitVargenSuffix(name string) (base, suffix string) { - i := len(name) - for i > 0 && name[i-1] >= '0' && name[i-1] <= '9' { - i-- - } - const dot = "·" - if i >= len(dot) && name[i-len(dot):i] == dot { - i -= len(dot) - return name[:i], name[i:] - } - return name, "" -} diff --git a/vendor/golang.org/x/tools/internal/gcimporter/unified_no.go b/vendor/golang.org/x/tools/internal/gcimporter/unified_no.go deleted file mode 100644 index 38b624cada..0000000000 --- a/vendor/golang.org/x/tools/internal/gcimporter/unified_no.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !goexperiment.unified -// +build !goexperiment.unified - -package gcimporter - -const unifiedIR = false diff --git a/vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go b/vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go deleted file mode 100644 index b5118d0b3a..0000000000 --- a/vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build goexperiment.unified -// +build goexperiment.unified - -package gcimporter - -const unifiedIR = true diff --git a/vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go b/vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go index f0742f5404..522287d18d 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go @@ -11,10 +11,10 @@ import ( "go/token" "go/types" "sort" - "strings" "golang.org/x/tools/internal/aliases" "golang.org/x/tools/internal/pkgbits" + "golang.org/x/tools/internal/typesinternal" ) // A pkgReader holds the shared state for reading a unified IR package @@ -71,7 +71,6 @@ func UImportData(fset *token.FileSet, imports map[string]*types.Package, data [] } s := string(data) - s = s[:strings.LastIndex(s, "\n$$\n")] input := pkgbits.NewPkgDecoder(path, s) pkg = readUnifiedPackage(fset, nil, imports, input) return @@ -266,7 +265,12 @@ func (pr *pkgReader) pkgIdx(idx pkgbits.Index) *types.Package { func (r *reader) doPkg() *types.Package { path := r.String() switch path { - case "": + // cmd/compile emits path="main" for main packages because + // that's the linker symbol prefix it used; but we need + // the package's path as it would be reported by go list, + // hence "main" below. + // See test at go/packages.TestMainPackagePathInModeTypes. + case "", "main": path = r.p.PkgPath() case "builtin": return nil // universe @@ -562,13 +566,14 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) { // If the underlying type is an interface, we need to // duplicate its methods so we can replace the receiver // parameter's type (#49906). - if iface, ok := aliases.Unalias(underlying).(*types.Interface); ok && iface.NumExplicitMethods() != 0 { + if iface, ok := types.Unalias(underlying).(*types.Interface); ok && iface.NumExplicitMethods() != 0 { methods := make([]*types.Func, iface.NumExplicitMethods()) for i := range methods { fn := iface.ExplicitMethod(i) sig := fn.Type().(*types.Signature) recv := types.NewVar(fn.Pos(), fn.Pkg(), "", named) + typesinternal.SetVarKind(recv, typesinternal.RecvVar) methods[i] = types.NewFunc(fn.Pos(), fn.Pkg(), fn.Name(), types.NewSignature(recv, sig.Params(), sig.Results(), sig.Variadic())) } @@ -616,7 +621,9 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) { case pkgbits.ObjVar: pos := r.pos() typ := r.typ() - declare(types.NewVar(pos, objPkg, objName, typ)) + v := types.NewVar(pos, objPkg, objName, typ) + typesinternal.SetVarKind(v, typesinternal.PackageVar) + declare(v) } } @@ -738,3 +745,17 @@ func pkgScope(pkg *types.Package) *types.Scope { } return types.Universe } + +// See cmd/compile/internal/types.SplitVargenSuffix. +func splitVargenSuffix(name string) (base, suffix string) { + i := len(name) + for i > 0 && name[i-1] >= '0' && name[i-1] <= '9' { + i-- + } + const dot = "·" + if i >= len(dot) && name[i-len(dot):i] == dot { + i -= len(dot) + return name[:i], name[i:] + } + return name, "" +} diff --git a/vendor/golang.org/x/tools/internal/gocommand/invoke.go b/vendor/golang.org/x/tools/internal/gocommand/invoke.go index 2e59ff8558..7ea9013447 100644 --- a/vendor/golang.org/x/tools/internal/gocommand/invoke.go +++ b/vendor/golang.org/x/tools/internal/gocommand/invoke.go @@ -16,7 +16,6 @@ import ( "os" "os/exec" "path/filepath" - "reflect" "regexp" "runtime" "strconv" @@ -29,7 +28,7 @@ import ( "golang.org/x/tools/internal/event/label" ) -// An Runner will run go command invocations and serialize +// A Runner will run go command invocations and serialize // them if it sees a concurrency error. type Runner struct { // once guards the runner initialization. @@ -180,7 +179,7 @@ type Invocation struct { CleanEnv bool Env []string WorkingDir string - Logf func(format string, args ...interface{}) + Logf func(format string, args ...any) } // Postcondition: both error results have same nilness. @@ -250,16 +249,13 @@ func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error { cmd.Stdout = stdout cmd.Stderr = stderr - // cmd.WaitDelay was added only in go1.20 (see #50436). - if waitDelay := reflect.ValueOf(cmd).Elem().FieldByName("WaitDelay"); waitDelay.IsValid() { - // https://go.dev/issue/59541: don't wait forever copying stderr - // after the command has exited. - // After CL 484741 we copy stdout manually, so we we'll stop reading that as - // soon as ctx is done. However, we also don't want to wait around forever - // for stderr. Give a much-longer-than-reasonable delay and then assume that - // something has wedged in the kernel or runtime. - waitDelay.Set(reflect.ValueOf(30 * time.Second)) - } + // https://go.dev/issue/59541: don't wait forever copying stderr + // after the command has exited. + // After CL 484741 we copy stdout manually, so we we'll stop reading that as + // soon as ctx is done. However, we also don't want to wait around forever + // for stderr. Give a much-longer-than-reasonable delay and then assume that + // something has wedged in the kernel or runtime. + cmd.WaitDelay = 30 * time.Second // The cwd gets resolved to the real path. On Darwin, where // /tmp is a symlink, this breaks anything that expects the @@ -392,7 +388,9 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) { case err := <-resChan: return err case <-timer.C: - HandleHangingGoCommand(startTime, cmd) + // HandleHangingGoCommand terminates this process. + // Pass off resChan in case we can collect the command error. + handleHangingGoCommand(startTime, cmd, resChan) case <-ctx.Done(): } } else { @@ -417,8 +415,6 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) { } // Didn't shut down in response to interrupt. Kill it hard. - // TODO(rfindley): per advice from bcmills@, it may be better to send SIGQUIT - // on certain platforms, such as unix. if err := cmd.Process.Kill(); err != nil && !errors.Is(err, os.ErrProcessDone) && debug { log.Printf("error killing the Go command: %v", err) } @@ -426,15 +422,17 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) { return <-resChan } -func HandleHangingGoCommand(start time.Time, cmd *exec.Cmd) { +// handleHangingGoCommand outputs debugging information to help diagnose the +// cause of a hanging Go command, and then exits with log.Fatalf. +func handleHangingGoCommand(start time.Time, cmd *exec.Cmd, resChan chan error) { switch runtime.GOOS { - case "linux", "darwin", "freebsd", "netbsd": + case "linux", "darwin", "freebsd", "netbsd", "openbsd": fmt.Fprintln(os.Stderr, `DETECTED A HANGING GO COMMAND -The gopls test runner has detected a hanging go command. In order to debug -this, the output of ps and lsof/fstat is printed below. + The gopls test runner has detected a hanging go command. In order to debug + this, the output of ps and lsof/fstat is printed below. -See golang/go#54461 for more details.`) + See golang/go#54461 for more details.`) fmt.Fprintln(os.Stderr, "\nps axo ppid,pid,command:") fmt.Fprintln(os.Stderr, "-------------------------") @@ -442,7 +440,7 @@ See golang/go#54461 for more details.`) psCmd.Stdout = os.Stderr psCmd.Stderr = os.Stderr if err := psCmd.Run(); err != nil { - panic(fmt.Sprintf("running ps: %v", err)) + log.Printf("Handling hanging Go command: running ps: %v", err) } listFiles := "lsof" @@ -456,10 +454,24 @@ See golang/go#54461 for more details.`) listFilesCmd.Stdout = os.Stderr listFilesCmd.Stderr = os.Stderr if err := listFilesCmd.Run(); err != nil { - panic(fmt.Sprintf("running %s: %v", listFiles, err)) + log.Printf("Handling hanging Go command: running %s: %v", listFiles, err) + } + // Try to extract information about the slow go process by issuing a SIGQUIT. + if err := cmd.Process.Signal(sigStuckProcess); err == nil { + select { + case err := <-resChan: + stderr := "not a bytes.Buffer" + if buf, _ := cmd.Stderr.(*bytes.Buffer); buf != nil { + stderr = buf.String() + } + log.Printf("Quit hanging go command:\n\terr:%v\n\tstderr:\n%v\n\n", err, stderr) + case <-time.After(5 * time.Second): + } + } else { + log.Printf("Sending signal %d to hanging go command: %v", sigStuckProcess, err) } } - panic(fmt.Sprintf("detected hanging go command (golang/go#54461); waited %s\n\tcommand:%s\n\tpid:%d", time.Since(start), cmd, cmd.Process.Pid)) + log.Fatalf("detected hanging go command (golang/go#54461); waited %s\n\tcommand:%s\n\tpid:%d", time.Since(start), cmd, cmd.Process.Pid) } func cmdDebugStr(cmd *exec.Cmd) string { diff --git a/vendor/golang.org/x/tools/internal/gocommand/invoke_notunix.go b/vendor/golang.org/x/tools/internal/gocommand/invoke_notunix.go new file mode 100644 index 0000000000..469c648e4d --- /dev/null +++ b/vendor/golang.org/x/tools/internal/gocommand/invoke_notunix.go @@ -0,0 +1,13 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !unix + +package gocommand + +import "os" + +// sigStuckProcess is the signal to send to kill a hanging subprocess. +// On Unix we send SIGQUIT, but on non-Unix we only have os.Kill. +var sigStuckProcess = os.Kill diff --git a/vendor/golang.org/x/tools/internal/gocommand/invoke_unix.go b/vendor/golang.org/x/tools/internal/gocommand/invoke_unix.go new file mode 100644 index 0000000000..169d37c8e9 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/gocommand/invoke_unix.go @@ -0,0 +1,13 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build unix + +package gocommand + +import "syscall" + +// Sigstuckprocess is the signal to send to kill a hanging subprocess. +// Send SIGQUIT to get a stack trace. +var sigStuckProcess = syscall.SIGQUIT diff --git a/vendor/golang.org/x/tools/internal/imports/fix.go b/vendor/golang.org/x/tools/internal/imports/fix.go index dc7d50a7a4..bf6b0aaddd 100644 --- a/vendor/golang.org/x/tools/internal/imports/fix.go +++ b/vendor/golang.org/x/tools/internal/imports/fix.go @@ -27,7 +27,6 @@ import ( "unicode" "unicode/utf8" - "golang.org/x/sync/errgroup" "golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/gocommand" @@ -91,18 +90,6 @@ type ImportFix struct { Relevance float64 // see pkg } -// An ImportInfo represents a single import statement. -type ImportInfo struct { - ImportPath string // import path, e.g. "crypto/rand". - Name string // import name, e.g. "crand", or "" if none. -} - -// A packageInfo represents what's known about a package. -type packageInfo struct { - name string // real package name, if known. - exports map[string]bool // known exports. -} - // parseOtherFiles parses all the Go files in srcDir except filename, including // test files if filename looks like a test. // @@ -131,7 +118,7 @@ func parseOtherFiles(ctx context.Context, fset *token.FileSet, srcDir, filename continue } - f, err := parser.ParseFile(fset, filepath.Join(srcDir, fi.Name()), nil, 0) + f, err := parser.ParseFile(fset, filepath.Join(srcDir, fi.Name()), nil, parser.SkipObjectResolution) if err != nil { continue } @@ -162,8 +149,8 @@ func addGlobals(f *ast.File, globals map[string]bool) { // collectReferences builds a map of selector expressions, from // left hand side (X) to a set of right hand sides (Sel). -func collectReferences(f *ast.File) references { - refs := references{} +func collectReferences(f *ast.File) References { + refs := References{} var visitor visitFn visitor = func(node ast.Node) ast.Visitor { @@ -233,7 +220,7 @@ func (p *pass) findMissingImport(pkg string, syms map[string]bool) *ImportInfo { allFound := true for right := range syms { - if !pkgInfo.exports[right] { + if !pkgInfo.Exports[right] { allFound = false break } @@ -246,11 +233,6 @@ func (p *pass) findMissingImport(pkg string, syms map[string]bool) *ImportInfo { return nil } -// references is set of references found in a Go file. The first map key is the -// left hand side of a selector expression, the second key is the right hand -// side, and the value should always be true. -type references map[string]map[string]bool - // A pass contains all the inputs and state necessary to fix a file's imports. // It can be modified in some ways during use; see comments below. type pass struct { @@ -258,27 +240,29 @@ type pass struct { fset *token.FileSet // fset used to parse f and its siblings. f *ast.File // the file being fixed. srcDir string // the directory containing f. - env *ProcessEnv // the environment to use for go commands, etc. - loadRealPackageNames bool // if true, load package names from disk rather than guessing them. - otherFiles []*ast.File // sibling files. + logf func(string, ...any) + source Source // the environment to use for go commands, etc. + loadRealPackageNames bool // if true, load package names from disk rather than guessing them. + otherFiles []*ast.File // sibling files. + goroot string // Intermediate state, generated by load. existingImports map[string][]*ImportInfo - allRefs references - missingRefs references + allRefs References + missingRefs References // Inputs to fix. These can be augmented between successive fix calls. lastTry bool // indicates that this is the last call and fix should clean up as best it can. candidates []*ImportInfo // candidate imports in priority order. - knownPackages map[string]*packageInfo // information about all known packages. + knownPackages map[string]*PackageInfo // information about all known packages. } // loadPackageNames saves the package names for everything referenced by imports. -func (p *pass) loadPackageNames(imports []*ImportInfo) error { - if p.env.Logf != nil { - p.env.Logf("loading package names for %v packages", len(imports)) +func (p *pass) loadPackageNames(ctx context.Context, imports []*ImportInfo) error { + if p.logf != nil { + p.logf("loading package names for %v packages", len(imports)) defer func() { - p.env.Logf("done loading package names for %v packages", len(imports)) + p.logf("done loading package names for %v packages", len(imports)) }() } var unknown []string @@ -289,20 +273,17 @@ func (p *pass) loadPackageNames(imports []*ImportInfo) error { unknown = append(unknown, imp.ImportPath) } - resolver, err := p.env.GetResolver() - if err != nil { - return err - } - - names, err := resolver.loadPackageNames(unknown, p.srcDir) + names, err := p.source.LoadPackageNames(ctx, p.srcDir, unknown) if err != nil { return err } + // TODO(rfindley): revisit this. Why do we need to store known packages with + // no exports? The inconsistent data is confusing. for path, name := range names { - p.knownPackages[path] = &packageInfo{ - name: name, - exports: map[string]bool{}, + p.knownPackages[path] = &PackageInfo{ + Name: name, + Exports: map[string]bool{}, } } return nil @@ -330,8 +311,8 @@ func (p *pass) importIdentifier(imp *ImportInfo) string { return imp.Name } known := p.knownPackages[imp.ImportPath] - if known != nil && known.name != "" { - return withoutVersion(known.name) + if known != nil && known.Name != "" { + return withoutVersion(known.Name) } return ImportPathToAssumedName(imp.ImportPath) } @@ -339,9 +320,9 @@ func (p *pass) importIdentifier(imp *ImportInfo) string { // load reads in everything necessary to run a pass, and reports whether the // file already has all the imports it needs. It fills in p.missingRefs with the // file's missing symbols, if any, or removes unused imports if not. -func (p *pass) load() ([]*ImportFix, bool) { - p.knownPackages = map[string]*packageInfo{} - p.missingRefs = references{} +func (p *pass) load(ctx context.Context) ([]*ImportFix, bool) { + p.knownPackages = map[string]*PackageInfo{} + p.missingRefs = References{} p.existingImports = map[string][]*ImportInfo{} // Load basic information about the file in question. @@ -364,9 +345,11 @@ func (p *pass) load() ([]*ImportFix, bool) { // f's imports by the identifier they introduce. imports := collectImports(p.f) if p.loadRealPackageNames { - err := p.loadPackageNames(append(imports, p.candidates...)) + err := p.loadPackageNames(ctx, append(imports, p.candidates...)) if err != nil { - p.env.logf("loading package names: %v", err) + if p.logf != nil { + p.logf("loading package names: %v", err) + } return nil, false } } @@ -535,9 +518,10 @@ func (p *pass) assumeSiblingImportsValid() { // We have the stdlib in memory; no need to guess. rights = symbolNameSet(m) } - p.addCandidate(imp, &packageInfo{ + // TODO(rfindley): we should set package name here, for consistency. + p.addCandidate(imp, &PackageInfo{ // no name; we already know it. - exports: rights, + Exports: rights, }) } } @@ -546,14 +530,14 @@ func (p *pass) assumeSiblingImportsValid() { // addCandidate adds a candidate import to p, and merges in the information // in pkg. -func (p *pass) addCandidate(imp *ImportInfo, pkg *packageInfo) { +func (p *pass) addCandidate(imp *ImportInfo, pkg *PackageInfo) { p.candidates = append(p.candidates, imp) if existing, ok := p.knownPackages[imp.ImportPath]; ok { - if existing.name == "" { - existing.name = pkg.name + if existing.Name == "" { + existing.Name = pkg.Name } - for export := range pkg.exports { - existing.exports[export] = true + for export := range pkg.Exports { + existing.Exports[export] = true } } else { p.knownPackages[imp.ImportPath] = pkg @@ -581,19 +565,42 @@ func fixImportsDefault(fset *token.FileSet, f *ast.File, filename string, env *P // getFixes gets the import fixes that need to be made to f in order to fix the imports. // It does not modify the ast. func getFixes(ctx context.Context, fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv) ([]*ImportFix, error) { + source, err := NewProcessEnvSource(env, filename, f.Name.Name) + if err != nil { + return nil, err + } + goEnv, err := env.goEnv() + if err != nil { + return nil, err + } + return getFixesWithSource(ctx, fset, f, filename, goEnv["GOROOT"], env.logf, source) +} + +func getFixesWithSource(ctx context.Context, fset *token.FileSet, f *ast.File, filename string, goroot string, logf func(string, ...any), source Source) ([]*ImportFix, error) { + // This logic is defensively duplicated from getFixes. abs, err := filepath.Abs(filename) if err != nil { return nil, err } srcDir := filepath.Dir(abs) - env.logf("fixImports(filename=%q), abs=%q, srcDir=%q ...", filename, abs, srcDir) + + if logf != nil { + logf("fixImports(filename=%q), srcDir=%q ...", filename, abs, srcDir) + } // First pass: looking only at f, and using the naive algorithm to // derive package names from import paths, see if the file is already // complete. We can't add any imports yet, because we don't know // if missing references are actually package vars. - p := &pass{fset: fset, f: f, srcDir: srcDir, env: env} - if fixes, done := p.load(); done { + p := &pass{ + fset: fset, + f: f, + srcDir: srcDir, + logf: logf, + goroot: goroot, + source: source, + } + if fixes, done := p.load(ctx); done { return fixes, nil } @@ -605,7 +612,7 @@ func getFixes(ctx context.Context, fset *token.FileSet, f *ast.File, filename st // Second pass: add information from other files in the same package, // like their package vars and imports. p.otherFiles = otherFiles - if fixes, done := p.load(); done { + if fixes, done := p.load(ctx); done { return fixes, nil } @@ -618,10 +625,17 @@ func getFixes(ctx context.Context, fset *token.FileSet, f *ast.File, filename st // Third pass: get real package names where we had previously used // the naive algorithm. - p = &pass{fset: fset, f: f, srcDir: srcDir, env: env} + p = &pass{ + fset: fset, + f: f, + srcDir: srcDir, + logf: logf, + goroot: goroot, + source: p.source, // safe to reuse, as it's just a wrapper around env + } p.loadRealPackageNames = true p.otherFiles = otherFiles - if fixes, done := p.load(); done { + if fixes, done := p.load(ctx); done { return fixes, nil } @@ -766,7 +780,7 @@ func GetAllCandidates(ctx context.Context, wrapped func(ImportFix), searchPrefix return true }, dirFound: func(pkg *pkg) bool { - if !canUse(filename, pkg.dir) { + if !CanUse(filename, pkg.dir) { return false } // Try the assumed package name first, then a simpler path match @@ -801,7 +815,7 @@ func GetImportPaths(ctx context.Context, wrapped func(ImportFix), searchPrefix, return true }, dirFound: func(pkg *pkg) bool { - if !canUse(filename, pkg.dir) { + if !CanUse(filename, pkg.dir) { return false } return strings.HasPrefix(pkg.importPathShort, searchPrefix) @@ -835,7 +849,7 @@ func GetPackageExports(ctx context.Context, wrapped func(PackageExport), searchP return true }, dirFound: func(pkg *pkg) bool { - return pkgIsCandidate(filename, references{searchPkg: nil}, pkg) + return pkgIsCandidate(filename, References{searchPkg: nil}, pkg) }, packageNameLoaded: func(pkg *pkg) bool { return pkg.packageName == searchPkg @@ -913,7 +927,7 @@ type ProcessEnv struct { WorkingDir string // If Logf is non-nil, debug logging is enabled through this function. - Logf func(format string, args ...interface{}) + Logf func(format string, args ...any) // If set, ModCache holds a shared cache of directory info to use across // multiple ProcessEnvs. @@ -1086,11 +1100,7 @@ func (e *ProcessEnv) invokeGo(ctx context.Context, verb string, args ...string) return e.GocmdRunner.Run(ctx, inv) } -func addStdlibCandidates(pass *pass, refs references) error { - goenv, err := pass.env.goEnv() - if err != nil { - return err - } +func addStdlibCandidates(pass *pass, refs References) error { localbase := func(nm string) string { ans := path.Base(nm) if ans[0] == 'v' { @@ -1105,13 +1115,13 @@ func addStdlibCandidates(pass *pass, refs references) error { } add := func(pkg string) { // Prevent self-imports. - if path.Base(pkg) == pass.f.Name.Name && filepath.Join(goenv["GOROOT"], "src", pkg) == pass.srcDir { + if path.Base(pkg) == pass.f.Name.Name && filepath.Join(pass.goroot, "src", pkg) == pass.srcDir { return } exports := symbolNameSet(stdlib.PackageSymbols[pkg]) pass.addCandidate( &ImportInfo{ImportPath: pkg}, - &packageInfo{name: localbase(pkg), exports: exports}) + &PackageInfo{Name: localbase(pkg), Exports: exports}) } for left := range refs { if left == "rand" { @@ -1122,6 +1132,9 @@ func addStdlibCandidates(pass *pass, refs references) error { // but we have no way of figuring out what the user is using // TODO: investigate using the toolchain version to disambiguate in the stdlib add("math/rand/v2") + // math/rand has an overlapping API + // TestIssue66407 fails without this + add("math/rand") continue } for importPath := range stdlib.PackageSymbols { @@ -1175,91 +1188,14 @@ type scanCallback struct { exportsLoaded func(pkg *pkg, exports []stdlib.Symbol) } -func addExternalCandidates(ctx context.Context, pass *pass, refs references, filename string) error { +func addExternalCandidates(ctx context.Context, pass *pass, refs References, filename string) error { ctx, done := event.Start(ctx, "imports.addExternalCandidates") defer done() - var mu sync.Mutex - found := make(map[string][]pkgDistance) - callback := &scanCallback{ - rootFound: func(gopathwalk.Root) bool { - return true // We want everything. - }, - dirFound: func(pkg *pkg) bool { - return pkgIsCandidate(filename, refs, pkg) - }, - packageNameLoaded: func(pkg *pkg) bool { - if _, want := refs[pkg.packageName]; !want { - return false - } - if pkg.dir == pass.srcDir && pass.f.Name.Name == pkg.packageName { - // The candidate is in the same directory and has the - // same package name. Don't try to import ourselves. - return false - } - if !canUse(filename, pkg.dir) { - return false - } - mu.Lock() - defer mu.Unlock() - found[pkg.packageName] = append(found[pkg.packageName], pkgDistance{pkg, distance(pass.srcDir, pkg.dir)}) - return false // We'll do our own loading after we sort. - }, - } - resolver, err := pass.env.GetResolver() + results, err := pass.source.ResolveReferences(ctx, filename, refs) if err != nil { return err } - if err = resolver.scan(ctx, callback); err != nil { - return err - } - - // Search for imports matching potential package references. - type result struct { - imp *ImportInfo - pkg *packageInfo - } - results := make([]*result, len(refs)) - - g, ctx := errgroup.WithContext(ctx) - - searcher := symbolSearcher{ - logf: pass.env.logf, - srcDir: pass.srcDir, - xtest: strings.HasSuffix(pass.f.Name.Name, "_test"), - loadExports: resolver.loadExports, - } - - i := 0 - for pkgName, symbols := range refs { - index := i // claim an index in results - i++ - pkgName := pkgName - symbols := symbols - - g.Go(func() error { - found, err := searcher.search(ctx, found[pkgName], pkgName, symbols) - if err != nil { - return err - } - if found == nil { - return nil // No matching package. - } - - imp := &ImportInfo{ - ImportPath: found.importPathShort, - } - pkg := &packageInfo{ - name: pkgName, - exports: symbols, - } - results[index] = &result{imp, pkg} - return nil - }) - } - if err := g.Wait(); err != nil { - return err - } for _, result := range results { if result == nil { @@ -1267,7 +1203,7 @@ func addExternalCandidates(ctx context.Context, pass *pass, refs references, fil } // Don't offer completions that would shadow predeclared // names, such as github.com/coreos/etcd/error. - if types.Universe.Lookup(result.pkg.name) != nil { // predeclared + if types.Universe.Lookup(result.Package.Name) != nil { // predeclared // Ideally we would skip this candidate only // if the predeclared name is actually // referenced by the file, but that's a lot @@ -1276,7 +1212,7 @@ func addExternalCandidates(ctx context.Context, pass *pass, refs references, fil // user before long. continue } - pass.addCandidate(result.imp, result.pkg) + pass.addCandidate(result.Import, result.Package) } return nil } @@ -1620,6 +1556,7 @@ func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string, incl } fullFile := filepath.Join(dir, fi.Name()) + // Legacy ast.Object resolution is needed here. f, err := parser.ParseFile(fset, fullFile, nil, 0) if err != nil { env.logf("error parsing %v: %v", fullFile, err) @@ -1800,9 +1737,9 @@ func (s *symbolSearcher) searchOne(ctx context.Context, c pkgDistance, symbols m // filename is the file being formatted. // pkgIdent is the package being searched for, like "client" (if // searching for "client.New") -func pkgIsCandidate(filename string, refs references, pkg *pkg) bool { +func pkgIsCandidate(filename string, refs References, pkg *pkg) bool { // Check "internal" and "vendor" visibility: - if !canUse(filename, pkg.dir) { + if !CanUse(filename, pkg.dir) { return false } @@ -1825,9 +1762,9 @@ func pkgIsCandidate(filename string, refs references, pkg *pkg) bool { return false } -// canUse reports whether the package in dir is usable from filename, +// CanUse reports whether the package in dir is usable from filename, // respecting the Go "internal" and "vendor" visibility rules. -func canUse(filename, dir string) bool { +func CanUse(filename, dir string) bool { // Fast path check, before any allocations. If it doesn't contain vendor // or internal, it's not tricky: // Note that this can false-negative on directories like "notinternal", diff --git a/vendor/golang.org/x/tools/internal/imports/imports.go b/vendor/golang.org/x/tools/internal/imports/imports.go index f83465520a..2215a12880 100644 --- a/vendor/golang.org/x/tools/internal/imports/imports.go +++ b/vendor/golang.org/x/tools/internal/imports/imports.go @@ -47,7 +47,14 @@ type Options struct { // Process implements golang.org/x/tools/imports.Process with explicit context in opt.Env. func Process(filename string, src []byte, opt *Options) (formatted []byte, err error) { fileSet := token.NewFileSet() - file, adjust, err := parse(fileSet, filename, src, opt) + var parserMode parser.Mode + if opt.Comments { + parserMode |= parser.ParseComments + } + if opt.AllErrors { + parserMode |= parser.AllErrors + } + file, adjust, err := parse(fileSet, filename, src, parserMode, opt.Fragment) if err != nil { return nil, err } @@ -66,17 +73,19 @@ func Process(filename string, src []byte, opt *Options) (formatted []byte, err e // // Note that filename's directory influences which imports can be chosen, // so it is important that filename be accurate. -func FixImports(ctx context.Context, filename string, src []byte, opt *Options) (fixes []*ImportFix, err error) { +func FixImports(ctx context.Context, filename string, src []byte, goroot string, logf func(string, ...any), source Source) (fixes []*ImportFix, err error) { ctx, done := event.Start(ctx, "imports.FixImports") defer done() fileSet := token.NewFileSet() - file, _, err := parse(fileSet, filename, src, opt) + // TODO(rfindley): these default values for ParseComments and AllErrors were + // extracted from gopls, but are they even needed? + file, _, err := parse(fileSet, filename, src, parser.ParseComments|parser.AllErrors, true) if err != nil { return nil, err } - return getFixes(ctx, fileSet, file, filename, opt.Env) + return getFixesWithSource(ctx, fileSet, file, filename, goroot, logf, source) } // ApplyFixes applies all of the fixes to the file and formats it. extraMode @@ -86,7 +95,7 @@ func ApplyFixes(fixes []*ImportFix, filename string, src []byte, opt *Options, e // Don't use parse() -- we don't care about fragments or statement lists // here, and we need to work with unparseable files. fileSet := token.NewFileSet() - parserMode := parser.Mode(0) + parserMode := parser.SkipObjectResolution if opt.Comments { parserMode |= parser.ParseComments } @@ -114,7 +123,7 @@ func ApplyFixes(fixes []*ImportFix, filename string, src []byte, opt *Options, e // formatted file, and returns the postpocessed result. func formatFile(fset *token.FileSet, file *ast.File, src []byte, adjust func(orig []byte, src []byte) []byte, opt *Options) ([]byte, error) { mergeImports(file) - sortImports(opt.LocalPrefix, fset.File(file.Pos()), file) + sortImports(opt.LocalPrefix, fset.File(file.FileStart), file) var spacesBefore []string // import paths we need spaces before for _, impSection := range astutil.Imports(fset, file) { // Within each block of contiguous imports, see if any @@ -164,13 +173,9 @@ func formatFile(fset *token.FileSet, file *ast.File, src []byte, adjust func(ori // parse parses src, which was read from filename, // as a Go source file or statement list. -func parse(fset *token.FileSet, filename string, src []byte, opt *Options) (*ast.File, func(orig, src []byte) []byte, error) { - parserMode := parser.Mode(0) - if opt.Comments { - parserMode |= parser.ParseComments - } - if opt.AllErrors { - parserMode |= parser.AllErrors +func parse(fset *token.FileSet, filename string, src []byte, parserMode parser.Mode, fragment bool) (*ast.File, func(orig, src []byte) []byte, error) { + if parserMode&parser.SkipObjectResolution != 0 { + panic("legacy ast.Object resolution is required") } // Try as whole source file. @@ -181,7 +186,7 @@ func parse(fset *token.FileSet, filename string, src []byte, opt *Options) (*ast // If the error is that the source file didn't begin with a // package line and we accept fragmented input, fall through to // try as a source fragment. Stop and return on any other error. - if !opt.Fragment || !strings.Contains(err.Error(), "expected 'package'") { + if !fragment || !strings.Contains(err.Error(), "expected 'package'") { return nil, nil, err } diff --git a/vendor/golang.org/x/tools/internal/imports/source.go b/vendor/golang.org/x/tools/internal/imports/source.go new file mode 100644 index 0000000000..cbe4f3c5ba --- /dev/null +++ b/vendor/golang.org/x/tools/internal/imports/source.go @@ -0,0 +1,63 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package imports + +import "context" + +// These types document the APIs below. +// +// TODO(rfindley): consider making these defined types rather than aliases. +type ( + ImportPath = string + PackageName = string + Symbol = string + + // References is set of References found in a Go file. The first map key is the + // left hand side of a selector expression, the second key is the right hand + // side, and the value should always be true. + References = map[PackageName]map[Symbol]bool +) + +// A Result satisfies a missing import. +// +// The Import field describes the missing import spec, and the Package field +// summarizes the package exports. +type Result struct { + Import *ImportInfo + Package *PackageInfo +} + +// An ImportInfo represents a single import statement. +type ImportInfo struct { + ImportPath string // import path, e.g. "crypto/rand". + Name string // import name, e.g. "crand", or "" if none. +} + +// A PackageInfo represents what's known about a package. +type PackageInfo struct { + Name string // package name in the package declaration, if known + Exports map[string]bool // set of names of known package level sortSymbols +} + +// A Source provides imports to satisfy unresolved references in the file being +// fixed. +type Source interface { + // LoadPackageNames queries PackageName information for the requested import + // paths, when operating from the provided srcDir. + // + // TODO(rfindley): try to refactor to remove this operation. + LoadPackageNames(ctx context.Context, srcDir string, paths []ImportPath) (map[ImportPath]PackageName, error) + + // ResolveReferences asks the Source for the best package name to satisfy + // each of the missing references, in the context of fixing the given + // filename. + // + // Returns a map from package name to a [Result] for that package name that + // provides the required symbols. Keys may be omitted in the map if no + // candidates satisfy all missing references for that package name. It is up + // to each data source to select the best result for each entry in the + // missing map. + ResolveReferences(ctx context.Context, filename string, missing References) ([]*Result, error) +} diff --git a/vendor/golang.org/x/tools/internal/imports/source_env.go b/vendor/golang.org/x/tools/internal/imports/source_env.go new file mode 100644 index 0000000000..ec996c3ccf --- /dev/null +++ b/vendor/golang.org/x/tools/internal/imports/source_env.go @@ -0,0 +1,129 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package imports + +import ( + "context" + "path/filepath" + "strings" + "sync" + + "golang.org/x/sync/errgroup" + "golang.org/x/tools/internal/gopathwalk" +) + +// ProcessEnvSource implements the [Source] interface using the legacy +// [ProcessEnv] abstraction. +type ProcessEnvSource struct { + env *ProcessEnv + srcDir string + filename string + pkgName string +} + +// NewProcessEnvSource returns a [ProcessEnvSource] wrapping the given +// env, to be used for fixing imports in the file with name filename in package +// named pkgName. +func NewProcessEnvSource(env *ProcessEnv, filename, pkgName string) (*ProcessEnvSource, error) { + abs, err := filepath.Abs(filename) + if err != nil { + return nil, err + } + srcDir := filepath.Dir(abs) + return &ProcessEnvSource{ + env: env, + srcDir: srcDir, + filename: filename, + pkgName: pkgName, + }, nil +} + +func (s *ProcessEnvSource) LoadPackageNames(ctx context.Context, srcDir string, unknown []string) (map[string]string, error) { + r, err := s.env.GetResolver() + if err != nil { + return nil, err + } + return r.loadPackageNames(unknown, srcDir) +} + +func (s *ProcessEnvSource) ResolveReferences(ctx context.Context, filename string, refs map[string]map[string]bool) ([]*Result, error) { + var mu sync.Mutex + found := make(map[string][]pkgDistance) + callback := &scanCallback{ + rootFound: func(gopathwalk.Root) bool { + return true // We want everything. + }, + dirFound: func(pkg *pkg) bool { + return pkgIsCandidate(filename, refs, pkg) + }, + packageNameLoaded: func(pkg *pkg) bool { + if _, want := refs[pkg.packageName]; !want { + return false + } + if pkg.dir == s.srcDir && s.pkgName == pkg.packageName { + // The candidate is in the same directory and has the + // same package name. Don't try to import ourselves. + return false + } + if !CanUse(filename, pkg.dir) { + return false + } + mu.Lock() + defer mu.Unlock() + found[pkg.packageName] = append(found[pkg.packageName], pkgDistance{pkg, distance(s.srcDir, pkg.dir)}) + return false // We'll do our own loading after we sort. + }, + } + resolver, err := s.env.GetResolver() + if err != nil { + return nil, err + } + if err := resolver.scan(ctx, callback); err != nil { + return nil, err + } + + g, ctx := errgroup.WithContext(ctx) + + searcher := symbolSearcher{ + logf: s.env.logf, + srcDir: s.srcDir, + xtest: strings.HasSuffix(s.pkgName, "_test"), + loadExports: resolver.loadExports, + } + + var resultMu sync.Mutex + results := make(map[string]*Result, len(refs)) + for pkgName, symbols := range refs { + g.Go(func() error { + found, err := searcher.search(ctx, found[pkgName], pkgName, symbols) + if err != nil { + return err + } + if found == nil { + return nil // No matching package. + } + + imp := &ImportInfo{ + ImportPath: found.importPathShort, + } + pkg := &PackageInfo{ + Name: pkgName, + Exports: symbols, + } + resultMu.Lock() + results[pkgName] = &Result{Import: imp, Package: pkg} + resultMu.Unlock() + return nil + }) + } + if err := g.Wait(); err != nil { + return nil, err + } + var ans []*Result + for _, x := range results { + ans = append(ans, x) + } + return ans, nil +} diff --git a/vendor/golang.org/x/tools/internal/imports/source_modindex.go b/vendor/golang.org/x/tools/internal/imports/source_modindex.go new file mode 100644 index 0000000000..05229f06ce --- /dev/null +++ b/vendor/golang.org/x/tools/internal/imports/source_modindex.go @@ -0,0 +1,103 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package imports + +import ( + "context" + "sync" + "time" + + "golang.org/x/tools/internal/modindex" +) + +// This code is here rather than in the modindex package +// to avoid import loops + +// implements Source using modindex, so only for module cache. +// +// this is perhaps over-engineered. A new Index is read at first use. +// And then Update is called after every 15 minutes, and a new Index +// is read if the index changed. It is not clear the Mutex is needed. +type IndexSource struct { + modcachedir string + mutex sync.Mutex + ix *modindex.Index + expires time.Time +} + +// create a new Source. Called from NewView in cache/session.go. +func NewIndexSource(cachedir string) *IndexSource { + return &IndexSource{modcachedir: cachedir} +} + +func (s *IndexSource) LoadPackageNames(ctx context.Context, srcDir string, paths []ImportPath) (map[ImportPath]PackageName, error) { + /// This is used by goimports to resolve the package names of imports of the + // current package, which is irrelevant for the module cache. + return nil, nil +} + +func (s *IndexSource) ResolveReferences(ctx context.Context, filename string, missing References) ([]*Result, error) { + if err := s.maybeReadIndex(); err != nil { + return nil, err + } + var cs []modindex.Candidate + for pkg, nms := range missing { + for nm := range nms { + x := s.ix.Lookup(pkg, nm, false) + cs = append(cs, x...) + } + } + found := make(map[string]*Result) + for _, c := range cs { + var x *Result + if x = found[c.ImportPath]; x == nil { + x = &Result{ + Import: &ImportInfo{ + ImportPath: c.ImportPath, + Name: "", + }, + Package: &PackageInfo{ + Name: c.PkgName, + Exports: make(map[string]bool), + }, + } + found[c.ImportPath] = x + } + x.Package.Exports[c.Name] = true + } + var ans []*Result + for _, x := range found { + ans = append(ans, x) + } + return ans, nil +} + +func (s *IndexSource) maybeReadIndex() error { + s.mutex.Lock() + defer s.mutex.Unlock() + + var readIndex bool + if time.Now().After(s.expires) { + ok, err := modindex.Update(s.modcachedir) + if err != nil { + return err + } + if ok { + readIndex = true + } + } + + if readIndex || s.ix == nil { + ix, err := modindex.ReadIndex(s.modcachedir) + if err != nil { + return err + } + s.ix = ix + // for now refresh every 15 minutes + s.expires = time.Now().Add(time.Minute * 15) + } + + return nil +} diff --git a/vendor/golang.org/x/tools/internal/modindex/directories.go b/vendor/golang.org/x/tools/internal/modindex/directories.go new file mode 100644 index 0000000000..1e1a02f239 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/modindex/directories.go @@ -0,0 +1,135 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package modindex + +import ( + "fmt" + "log" + "os" + "path/filepath" + "regexp" + "slices" + "strings" + "sync" + "time" + + "golang.org/x/mod/semver" + "golang.org/x/tools/internal/gopathwalk" +) + +type directory struct { + path Relpath + importPath string + version string // semantic version + syms []symbol +} + +// filterDirs groups the directories by import path, +// sorting the ones with the same import path by semantic version, +// most recent first. +func byImportPath(dirs []Relpath) (map[string][]*directory, error) { + ans := make(map[string][]*directory) // key is import path + for _, d := range dirs { + ip, sv, err := DirToImportPathVersion(d) + if err != nil { + return nil, err + } + ans[ip] = append(ans[ip], &directory{ + path: d, + importPath: ip, + version: sv, + }) + } + for k, v := range ans { + semanticSort(v) + ans[k] = v + } + return ans, nil +} + +// sort the directories by semantic version, latest first +func semanticSort(v []*directory) { + slices.SortFunc(v, func(l, r *directory) int { + if n := semver.Compare(l.version, r.version); n != 0 { + return -n // latest first + } + return strings.Compare(string(l.path), string(r.path)) + }) +} + +// modCacheRegexp splits a relpathpath into module, module version, and package. +var modCacheRegexp = regexp.MustCompile(`(.*)@([^/\\]*)(.*)`) + +// DirToImportPathVersion computes import path and semantic version +func DirToImportPathVersion(dir Relpath) (string, string, error) { + m := modCacheRegexp.FindStringSubmatch(string(dir)) + // m[1] is the module path + // m[2] is the version major.minor.patch(-
 1 && flds[1][1] == 'D',
+			}
+			if px.Type == Func {
+				n, err := strconv.Atoi(flds[2])
+				if err != nil {
+					continue // should never happen
+				}
+				px.Results = int16(n)
+				if len(flds) >= 4 {
+					sig := strings.Split(flds[3], " ")
+					for i := 0; i < len(sig); i++ {
+						// $ cannot otherwise occur. removing the spaces
+						// almost works, but for chan struct{}, e.g.
+						sig[i] = strings.Replace(sig[i], "$", " ", -1)
+					}
+					px.Sig = toFields(sig)
+				}
+			}
+			ans = append(ans, px)
+		}
+	}
+	return ans
+}
+
+func toFields(sig []string) []Field {
+	ans := make([]Field, len(sig)/2)
+	for i := 0; i < len(ans); i++ {
+		ans[i] = Field{Arg: sig[2*i], Type: sig[2*i+1]}
+	}
+	return ans
+}
+
+// benchmarks show this is measurably better than strings.Split
+// split into first 4 fields separated by single space
+func fastSplit(x string) []string {
+	ans := make([]string, 0, 4)
+	nxt := 0
+	start := 0
+	for i := 0; i < len(x); i++ {
+		if x[i] != ' ' {
+			continue
+		}
+		ans = append(ans, x[start:i])
+		nxt++
+		start = i + 1
+		if nxt >= 3 {
+			break
+		}
+	}
+	ans = append(ans, x[start:])
+	return ans
+}
+
+func asLexType(c byte) LexType {
+	switch c {
+	case 'C':
+		return Const
+	case 'V':
+		return Var
+	case 'T':
+		return Type
+	case 'F':
+		return Func
+	}
+	return -1
+}
diff --git a/vendor/golang.org/x/tools/internal/modindex/modindex.go b/vendor/golang.org/x/tools/internal/modindex/modindex.go
new file mode 100644
index 0000000000..355a53e71a
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/modindex/modindex.go
@@ -0,0 +1,164 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package modindex contains code for building and searching an index to
+// the Go module cache. The directory containing the index, returned by
+// IndexDir(), contains a file index-name- that contains the name
+// of the current index. We believe writing that short file is atomic.
+// ReadIndex reads that file to get the file name of the index.
+// WriteIndex writes an index with a unique name and then
+// writes that name into a new version of index-name-.
+// ( stands for the CurrentVersion of the index format.)
+package modindex
+
+import (
+	"path/filepath"
+	"slices"
+	"strings"
+	"time"
+
+	"golang.org/x/mod/semver"
+)
+
+// Create always creates a new index for the go module cache that is in cachedir.
+func Create(cachedir string) error {
+	_, err := indexModCache(cachedir, true)
+	return err
+}
+
+// Update the index for the go module cache that is in cachedir,
+// If there is no existing index it will build one.
+// If there are changed directories since the last index, it will
+// write a new one and return true. Otherwise it returns false.
+func Update(cachedir string) (bool, error) {
+	return indexModCache(cachedir, false)
+}
+
+// indexModCache writes an index current as of when it is called.
+// If clear is true the index is constructed from all of GOMODCACHE
+// otherwise the index is constructed from the last previous index
+// and the updates to the cache. It returns true if it wrote an index,
+// false otherwise.
+func indexModCache(cachedir string, clear bool) (bool, error) {
+	cachedir, err := filepath.Abs(cachedir)
+	if err != nil {
+		return false, err
+	}
+	cd := Abspath(cachedir)
+	future := time.Now().Add(24 * time.Hour) // safely in the future
+	ok, err := modindexTimed(future, cd, clear)
+	if err != nil {
+		return false, err
+	}
+	return ok, nil
+}
+
+// modindexTimed writes an index current as of onlyBefore.
+// If clear is true the index is constructed from all of GOMODCACHE
+// otherwise the index is constructed from the last previous index
+// and all the updates to the cache before onlyBefore.
+// It returns true if it wrote a new index, false if it wrote nothing.
+func modindexTimed(onlyBefore time.Time, cachedir Abspath, clear bool) (bool, error) {
+	var curIndex *Index
+	if !clear {
+		var err error
+		curIndex, err = ReadIndex(string(cachedir))
+		if clear && err != nil {
+			return false, err
+		}
+		// TODO(pjw): check that most of those directories still exist
+	}
+	cfg := &work{
+		onlyBefore: onlyBefore,
+		oldIndex:   curIndex,
+		cacheDir:   cachedir,
+	}
+	if curIndex != nil {
+		cfg.onlyAfter = curIndex.Changed
+	}
+	if err := cfg.buildIndex(); err != nil {
+		return false, err
+	}
+	if len(cfg.newIndex.Entries) == 0 && curIndex != nil {
+		// no changes from existing curIndex, don't write a new index
+		return false, nil
+	}
+	if err := cfg.writeIndex(); err != nil {
+		return false, err
+	}
+	return true, nil
+}
+
+type work struct {
+	onlyBefore time.Time // do not use directories later than this
+	onlyAfter  time.Time // only interested in directories after this
+	// directories from before onlyAfter come from oldIndex
+	oldIndex *Index
+	newIndex *Index
+	cacheDir Abspath
+}
+
+func (w *work) buildIndex() error {
+	// The effective date of the new index should be at least
+	// slightly earlier than when the directories are scanned
+	// so set it now.
+	w.newIndex = &Index{Changed: time.Now(), Cachedir: w.cacheDir}
+	dirs := findDirs(string(w.cacheDir), w.onlyAfter, w.onlyBefore)
+	if len(dirs) == 0 {
+		return nil
+	}
+	newdirs, err := byImportPath(dirs)
+	if err != nil {
+		return err
+	}
+	// for each import path it might occur only in newdirs,
+	// only in w.oldIndex, or in both.
+	// If it occurs in both, use the semantically later one
+	if w.oldIndex != nil {
+		for _, e := range w.oldIndex.Entries {
+			found, ok := newdirs[e.ImportPath]
+			if !ok {
+				w.newIndex.Entries = append(w.newIndex.Entries, e)
+				continue // use this one, there is no new one
+			}
+			if semver.Compare(found[0].version, e.Version) > 0 {
+				// use the new one
+			} else {
+				// use the old one, forget the new one
+				w.newIndex.Entries = append(w.newIndex.Entries, e)
+				delete(newdirs, e.ImportPath)
+			}
+		}
+	}
+	// get symbol information for all the new diredtories
+	getSymbols(w.cacheDir, newdirs)
+	// assemble the new index entries
+	for k, v := range newdirs {
+		d := v[0]
+		pkg, names := processSyms(d.syms)
+		if pkg == "" {
+			continue // PJW: does this ever happen?
+		}
+		entry := Entry{
+			PkgName:    pkg,
+			Dir:        d.path,
+			ImportPath: k,
+			Version:    d.version,
+			Names:      names,
+		}
+		w.newIndex.Entries = append(w.newIndex.Entries, entry)
+	}
+	// sort the entries in the new index
+	slices.SortFunc(w.newIndex.Entries, func(l, r Entry) int {
+		if n := strings.Compare(l.PkgName, r.PkgName); n != 0 {
+			return n
+		}
+		return strings.Compare(l.ImportPath, r.ImportPath)
+	})
+	return nil
+}
+
+func (w *work) writeIndex() error {
+	return writeIndex(w.cacheDir, w.newIndex)
+}
diff --git a/vendor/golang.org/x/tools/internal/modindex/symbols.go b/vendor/golang.org/x/tools/internal/modindex/symbols.go
new file mode 100644
index 0000000000..b918529d43
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/modindex/symbols.go
@@ -0,0 +1,218 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package modindex
+
+import (
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"go/types"
+	"os"
+	"path/filepath"
+	"runtime"
+	"slices"
+	"strings"
+
+	"golang.org/x/sync/errgroup"
+)
+
+// The name of a symbol contains information about the symbol:
+//  T for types, TD if the type is deprecated
+//  C for consts, CD if the const is deprecated
+//  V for vars, VD if the var is deprecated
+// and for funcs:  F  ( )*
+// any spaces in  are replaced by $s so that the fields
+// of the name are space separated. F is replaced by FD if the func
+// is deprecated.
+type symbol struct {
+	pkg  string // name of the symbols's package
+	name string // declared name
+	kind string // T, C, V, or F, follwed by D if deprecated
+	sig  string // signature information, for F
+}
+
+// find the symbols for the best directories
+func getSymbols(cd Abspath, dirs map[string][]*directory) {
+	var g errgroup.Group
+	g.SetLimit(max(2, runtime.GOMAXPROCS(0)/2))
+	for _, vv := range dirs {
+		// throttling some day?
+		d := vv[0]
+		g.Go(func() error {
+			thedir := filepath.Join(string(cd), string(d.path))
+			mode := parser.SkipObjectResolution | parser.ParseComments
+
+			fi, err := os.ReadDir(thedir)
+			if err != nil {
+				return nil // log this someday?
+			}
+			for _, fx := range fi {
+				if !strings.HasSuffix(fx.Name(), ".go") || strings.HasSuffix(fx.Name(), "_test.go") {
+					continue
+				}
+				fname := filepath.Join(thedir, fx.Name())
+				tr, err := parser.ParseFile(token.NewFileSet(), fname, nil, mode)
+				if err != nil {
+					continue // ignore errors, someday log them?
+				}
+				d.syms = append(d.syms, getFileExports(tr)...)
+			}
+			return nil
+		})
+	}
+	g.Wait()
+}
+
+func getFileExports(f *ast.File) []symbol {
+	pkg := f.Name.Name
+	if pkg == "main" {
+		return nil
+	}
+	var ans []symbol
+	// should we look for //go:build ignore?
+	for _, decl := range f.Decls {
+		switch decl := decl.(type) {
+		case *ast.FuncDecl:
+			if decl.Recv != nil {
+				// ignore methods, as we are completing package selections
+				continue
+			}
+			name := decl.Name.Name
+			dtype := decl.Type
+			// not looking at dtype.TypeParams. That is, treating
+			// generic functions just like non-generic ones.
+			sig := dtype.Params
+			kind := "F"
+			if isDeprecated(decl.Doc) {
+				kind += "D"
+			}
+			result := []string{fmt.Sprintf("%d", dtype.Results.NumFields())}
+			for _, x := range sig.List {
+				// This code creates a string representing the type.
+				// TODO(pjw): it may be fragile:
+				// 1. x.Type could be nil, perhaps in ill-formed code
+				// 2. ExprString might someday change incompatibly to
+				//    include struct tags, which can be arbitrary strings
+				if x.Type == nil {
+					// Can this happen without a parse error? (Files with parse
+					// errors are ignored in getSymbols)
+					continue // maybe report this someday
+				}
+				tp := types.ExprString(x.Type)
+				if len(tp) == 0 {
+					// Can this happen?
+					continue // maybe report this someday
+				}
+				// This is only safe if ExprString never returns anything with a $
+				// The only place a $ can occur seems to be in a struct tag, which
+				// can be an arbitrary string literal, and ExprString does not presently
+				// print struct tags. So for this to happen the type of a formal parameter
+				// has to be a explict struct, e.g. foo(x struct{a int "$"}) and ExprString
+				// would have to show the struct tag. Even testing for this case seems
+				// a waste of effort, but let's remember the possibility
+				if strings.Contains(tp, "$") {
+					continue
+				}
+				tp = strings.Replace(tp, " ", "$", -1)
+				if len(x.Names) == 0 {
+					result = append(result, "_")
+					result = append(result, tp)
+				} else {
+					for _, y := range x.Names {
+						result = append(result, y.Name)
+						result = append(result, tp)
+					}
+				}
+			}
+			sigs := strings.Join(result, " ")
+			if s := newsym(pkg, name, kind, sigs); s != nil {
+				ans = append(ans, *s)
+			}
+		case *ast.GenDecl:
+			depr := isDeprecated(decl.Doc)
+			switch decl.Tok {
+			case token.CONST, token.VAR:
+				tp := "V"
+				if decl.Tok == token.CONST {
+					tp = "C"
+				}
+				if depr {
+					tp += "D"
+				}
+				for _, sp := range decl.Specs {
+					for _, x := range sp.(*ast.ValueSpec).Names {
+						if s := newsym(pkg, x.Name, tp, ""); s != nil {
+							ans = append(ans, *s)
+						}
+					}
+				}
+			case token.TYPE:
+				tp := "T"
+				if depr {
+					tp += "D"
+				}
+				for _, sp := range decl.Specs {
+					if s := newsym(pkg, sp.(*ast.TypeSpec).Name.Name, tp, ""); s != nil {
+						ans = append(ans, *s)
+					}
+				}
+			}
+		}
+	}
+	return ans
+}
+
+func newsym(pkg, name, kind, sig string) *symbol {
+	if len(name) == 0 || !ast.IsExported(name) {
+		return nil
+	}
+	sym := symbol{pkg: pkg, name: name, kind: kind, sig: sig}
+	return &sym
+}
+
+func isDeprecated(doc *ast.CommentGroup) bool {
+	if doc == nil {
+		return false
+	}
+	// go.dev/wiki/Deprecated Paragraph starting 'Deprecated:'
+	// This code fails for /* Deprecated: */, but it's the code from
+	// gopls/internal/analysis/deprecated
+	lines := strings.Split(doc.Text(), "\n\n")
+	for _, line := range lines {
+		if strings.HasPrefix(line, "Deprecated:") {
+			return true
+		}
+	}
+	return false
+}
+
+// return the package name and the value for the symbols.
+// if there are multiple packages, choose one arbitrarily
+// the returned slice is sorted lexicographically
+func processSyms(syms []symbol) (string, []string) {
+	if len(syms) == 0 {
+		return "", nil
+	}
+	slices.SortFunc(syms, func(l, r symbol) int {
+		return strings.Compare(l.name, r.name)
+	})
+	pkg := syms[0].pkg
+	var names []string
+	for _, s := range syms {
+		var nx string
+		if s.pkg == pkg {
+			if s.sig != "" {
+				nx = fmt.Sprintf("%s %s %s", s.name, s.kind, s.sig)
+			} else {
+				nx = fmt.Sprintf("%s %s", s.name, s.kind)
+			}
+			names = append(names, nx)
+		} else {
+			continue // PJW: do we want to keep track of these?
+		}
+	}
+	return pkg, names
+}
diff --git a/vendor/golang.org/x/tools/internal/modindex/types.go b/vendor/golang.org/x/tools/internal/modindex/types.go
new file mode 100644
index 0000000000..ece4488630
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/modindex/types.go
@@ -0,0 +1,25 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package modindex
+
+import (
+	"strings"
+)
+
+// some special types to avoid confusions
+
+// distinguish various types of directory names. It's easy to get confused.
+type Abspath string // absolute paths
+type Relpath string // paths with GOMODCACHE prefix removed
+
+func toRelpath(cachedir Abspath, s string) Relpath {
+	if strings.HasPrefix(s, string(cachedir)) {
+		if s == string(cachedir) {
+			return Relpath("")
+		}
+		return Relpath(s[len(cachedir)+1:])
+	}
+	return Relpath(s)
+}
diff --git a/vendor/golang.org/x/tools/internal/packagesinternal/packages.go b/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
index 44719de173..784605914e 100644
--- a/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
+++ b/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
@@ -5,8 +5,7 @@
 // Package packagesinternal exposes internal-only fields from go/packages.
 package packagesinternal
 
-var GetForTest = func(p interface{}) string { return "" }
-var GetDepsErrors = func(p interface{}) []*PackageError { return nil }
+var GetDepsErrors = func(p any) []*PackageError { return nil }
 
 type PackageError struct {
 	ImportStack []string // shortest path from package named on command line to this one
@@ -16,7 +15,6 @@ type PackageError struct {
 
 var TypecheckCgo int
 var DepsErrors int // must be set as a LoadMode to call GetDepsErrors
-var ForTest int    // must be set as a LoadMode to call GetForTest
 
-var SetModFlag = func(config interface{}, value string) {}
+var SetModFlag = func(config any, value string) {}
 var SetModFile = func(config interface{}, value string) {}
diff --git a/vendor/golang.org/x/tools/internal/stdlib/manifest.go b/vendor/golang.org/x/tools/internal/stdlib/manifest.go
index cdaac9ab34..9f0b871ff6 100644
--- a/vendor/golang.org/x/tools/internal/stdlib/manifest.go
+++ b/vendor/golang.org/x/tools/internal/stdlib/manifest.go
@@ -268,6 +268,8 @@ var PackageSymbols = map[string][]Symbol{
 		{"ErrTooLarge", Var, 0},
 		{"Fields", Func, 0},
 		{"FieldsFunc", Func, 0},
+		{"FieldsFuncSeq", Func, 24},
+		{"FieldsSeq", Func, 24},
 		{"HasPrefix", Func, 0},
 		{"HasSuffix", Func, 0},
 		{"Index", Func, 0},
@@ -280,6 +282,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"LastIndexAny", Func, 0},
 		{"LastIndexByte", Func, 5},
 		{"LastIndexFunc", Func, 0},
+		{"Lines", Func, 24},
 		{"Map", Func, 0},
 		{"MinRead", Const, 0},
 		{"NewBuffer", Func, 0},
@@ -293,7 +296,9 @@ var PackageSymbols = map[string][]Symbol{
 		{"Split", Func, 0},
 		{"SplitAfter", Func, 0},
 		{"SplitAfterN", Func, 0},
+		{"SplitAfterSeq", Func, 24},
 		{"SplitN", Func, 0},
+		{"SplitSeq", Func, 24},
 		{"Title", Func, 0},
 		{"ToLower", Func, 0},
 		{"ToLowerSpecial", Func, 0},
@@ -535,6 +540,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"NewCTR", Func, 0},
 		{"NewGCM", Func, 2},
 		{"NewGCMWithNonceSize", Func, 5},
+		{"NewGCMWithRandomNonce", Func, 24},
 		{"NewGCMWithTagSize", Func, 11},
 		{"NewOFB", Func, 0},
 		{"Stream", Type, 0},
@@ -673,6 +679,14 @@ var PackageSymbols = map[string][]Symbol{
 		{"Unmarshal", Func, 0},
 		{"UnmarshalCompressed", Func, 15},
 	},
+	"crypto/fips140": {
+		{"Enabled", Func, 24},
+	},
+	"crypto/hkdf": {
+		{"Expand", Func, 24},
+		{"Extract", Func, 24},
+		{"Key", Func, 24},
+	},
 	"crypto/hmac": {
 		{"Equal", Func, 1},
 		{"New", Func, 0},
@@ -683,11 +697,43 @@ var PackageSymbols = map[string][]Symbol{
 		{"Size", Const, 0},
 		{"Sum", Func, 2},
 	},
+	"crypto/mlkem": {
+		{"(*DecapsulationKey1024).Bytes", Method, 24},
+		{"(*DecapsulationKey1024).Decapsulate", Method, 24},
+		{"(*DecapsulationKey1024).EncapsulationKey", Method, 24},
+		{"(*DecapsulationKey768).Bytes", Method, 24},
+		{"(*DecapsulationKey768).Decapsulate", Method, 24},
+		{"(*DecapsulationKey768).EncapsulationKey", Method, 24},
+		{"(*EncapsulationKey1024).Bytes", Method, 24},
+		{"(*EncapsulationKey1024).Encapsulate", Method, 24},
+		{"(*EncapsulationKey768).Bytes", Method, 24},
+		{"(*EncapsulationKey768).Encapsulate", Method, 24},
+		{"CiphertextSize1024", Const, 24},
+		{"CiphertextSize768", Const, 24},
+		{"DecapsulationKey1024", Type, 24},
+		{"DecapsulationKey768", Type, 24},
+		{"EncapsulationKey1024", Type, 24},
+		{"EncapsulationKey768", Type, 24},
+		{"EncapsulationKeySize1024", Const, 24},
+		{"EncapsulationKeySize768", Const, 24},
+		{"GenerateKey1024", Func, 24},
+		{"GenerateKey768", Func, 24},
+		{"NewDecapsulationKey1024", Func, 24},
+		{"NewDecapsulationKey768", Func, 24},
+		{"NewEncapsulationKey1024", Func, 24},
+		{"NewEncapsulationKey768", Func, 24},
+		{"SeedSize", Const, 24},
+		{"SharedKeySize", Const, 24},
+	},
+	"crypto/pbkdf2": {
+		{"Key", Func, 24},
+	},
 	"crypto/rand": {
 		{"Int", Func, 0},
 		{"Prime", Func, 0},
 		{"Read", Func, 0},
 		{"Reader", Var, 0},
+		{"Text", Func, 24},
 	},
 	"crypto/rc4": {
 		{"(*Cipher).Reset", Method, 0},
@@ -766,6 +812,39 @@ var PackageSymbols = map[string][]Symbol{
 		{"Sum224", Func, 2},
 		{"Sum256", Func, 2},
 	},
+	"crypto/sha3": {
+		{"(*SHA3).AppendBinary", Method, 24},
+		{"(*SHA3).BlockSize", Method, 24},
+		{"(*SHA3).MarshalBinary", Method, 24},
+		{"(*SHA3).Reset", Method, 24},
+		{"(*SHA3).Size", Method, 24},
+		{"(*SHA3).Sum", Method, 24},
+		{"(*SHA3).UnmarshalBinary", Method, 24},
+		{"(*SHA3).Write", Method, 24},
+		{"(*SHAKE).AppendBinary", Method, 24},
+		{"(*SHAKE).BlockSize", Method, 24},
+		{"(*SHAKE).MarshalBinary", Method, 24},
+		{"(*SHAKE).Read", Method, 24},
+		{"(*SHAKE).Reset", Method, 24},
+		{"(*SHAKE).UnmarshalBinary", Method, 24},
+		{"(*SHAKE).Write", Method, 24},
+		{"New224", Func, 24},
+		{"New256", Func, 24},
+		{"New384", Func, 24},
+		{"New512", Func, 24},
+		{"NewCSHAKE128", Func, 24},
+		{"NewCSHAKE256", Func, 24},
+		{"NewSHAKE128", Func, 24},
+		{"NewSHAKE256", Func, 24},
+		{"SHA3", Type, 24},
+		{"SHAKE", Type, 24},
+		{"Sum224", Func, 24},
+		{"Sum256", Func, 24},
+		{"Sum384", Func, 24},
+		{"Sum512", Func, 24},
+		{"SumSHAKE128", Func, 24},
+		{"SumSHAKE256", Func, 24},
+	},
 	"crypto/sha512": {
 		{"BlockSize", Const, 0},
 		{"New", Func, 0},
@@ -788,6 +867,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"ConstantTimeEq", Func, 0},
 		{"ConstantTimeLessOrEq", Func, 2},
 		{"ConstantTimeSelect", Func, 0},
+		{"WithDataIndependentTiming", Func, 24},
 		{"XORBytes", Func, 20},
 	},
 	"crypto/tls": {
@@ -864,6 +944,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"ClientHelloInfo", Type, 4},
 		{"ClientHelloInfo.CipherSuites", Field, 4},
 		{"ClientHelloInfo.Conn", Field, 8},
+		{"ClientHelloInfo.Extensions", Field, 24},
 		{"ClientHelloInfo.ServerName", Field, 4},
 		{"ClientHelloInfo.SignatureSchemes", Field, 8},
 		{"ClientHelloInfo.SupportedCurves", Field, 4},
@@ -881,6 +962,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"Config.CurvePreferences", Field, 3},
 		{"Config.DynamicRecordSizingDisabled", Field, 7},
 		{"Config.EncryptedClientHelloConfigList", Field, 23},
+		{"Config.EncryptedClientHelloKeys", Field, 24},
 		{"Config.EncryptedClientHelloRejectionVerify", Field, 23},
 		{"Config.GetCertificate", Field, 4},
 		{"Config.GetClientCertificate", Field, 8},
@@ -934,6 +1016,10 @@ var PackageSymbols = map[string][]Symbol{
 		{"ECHRejectionError", Type, 23},
 		{"ECHRejectionError.RetryConfigList", Field, 23},
 		{"Ed25519", Const, 13},
+		{"EncryptedClientHelloKey", Type, 24},
+		{"EncryptedClientHelloKey.Config", Field, 24},
+		{"EncryptedClientHelloKey.PrivateKey", Field, 24},
+		{"EncryptedClientHelloKey.SendAsRetry", Field, 24},
 		{"InsecureCipherSuites", Func, 14},
 		{"Listen", Func, 0},
 		{"LoadX509KeyPair", Func, 0},
@@ -1032,6 +1118,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"VersionTLS12", Const, 2},
 		{"VersionTLS13", Const, 12},
 		{"X25519", Const, 8},
+		{"X25519MLKEM768", Const, 24},
 		{"X509KeyPair", Func, 0},
 	},
 	"crypto/x509": {
@@ -1056,6 +1143,8 @@ var PackageSymbols = map[string][]Symbol{
 		{"(ConstraintViolationError).Error", Method, 0},
 		{"(HostnameError).Error", Method, 0},
 		{"(InsecureAlgorithmError).Error", Method, 6},
+		{"(OID).AppendBinary", Method, 24},
+		{"(OID).AppendText", Method, 24},
 		{"(OID).Equal", Method, 22},
 		{"(OID).EqualASN1OID", Method, 22},
 		{"(OID).MarshalBinary", Method, 23},
@@ -1084,6 +1173,10 @@ var PackageSymbols = map[string][]Symbol{
 		{"Certificate.Extensions", Field, 2},
 		{"Certificate.ExtraExtensions", Field, 2},
 		{"Certificate.IPAddresses", Field, 1},
+		{"Certificate.InhibitAnyPolicy", Field, 24},
+		{"Certificate.InhibitAnyPolicyZero", Field, 24},
+		{"Certificate.InhibitPolicyMapping", Field, 24},
+		{"Certificate.InhibitPolicyMappingZero", Field, 24},
 		{"Certificate.IsCA", Field, 0},
 		{"Certificate.Issuer", Field, 0},
 		{"Certificate.IssuingCertificateURL", Field, 2},
@@ -1100,6 +1193,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"Certificate.PermittedURIDomains", Field, 10},
 		{"Certificate.Policies", Field, 22},
 		{"Certificate.PolicyIdentifiers", Field, 0},
+		{"Certificate.PolicyMappings", Field, 24},
 		{"Certificate.PublicKey", Field, 0},
 		{"Certificate.PublicKeyAlgorithm", Field, 0},
 		{"Certificate.Raw", Field, 0},
@@ -1107,6 +1201,8 @@ var PackageSymbols = map[string][]Symbol{
 		{"Certificate.RawSubject", Field, 0},
 		{"Certificate.RawSubjectPublicKeyInfo", Field, 0},
 		{"Certificate.RawTBSCertificate", Field, 0},
+		{"Certificate.RequireExplicitPolicy", Field, 24},
+		{"Certificate.RequireExplicitPolicyZero", Field, 24},
 		{"Certificate.SerialNumber", Field, 0},
 		{"Certificate.Signature", Field, 0},
 		{"Certificate.SignatureAlgorithm", Field, 0},
@@ -1198,6 +1294,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"NameConstraintsWithoutSANs", Const, 10},
 		{"NameMismatch", Const, 8},
 		{"NewCertPool", Func, 0},
+		{"NoValidChains", Const, 24},
 		{"NotAuthorizedToSign", Const, 0},
 		{"OID", Type, 22},
 		{"OIDFromInts", Func, 22},
@@ -1219,6 +1316,9 @@ var PackageSymbols = map[string][]Symbol{
 		{"ParsePKCS8PrivateKey", Func, 0},
 		{"ParsePKIXPublicKey", Func, 0},
 		{"ParseRevocationList", Func, 19},
+		{"PolicyMapping", Type, 24},
+		{"PolicyMapping.IssuerDomainPolicy", Field, 24},
+		{"PolicyMapping.SubjectDomainPolicy", Field, 24},
 		{"PublicKeyAlgorithm", Type, 0},
 		{"PureEd25519", Const, 13},
 		{"RSA", Const, 0},
@@ -1265,6 +1365,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"UnknownPublicKeyAlgorithm", Const, 0},
 		{"UnknownSignatureAlgorithm", Const, 0},
 		{"VerifyOptions", Type, 0},
+		{"VerifyOptions.CertificatePolicies", Field, 24},
 		{"VerifyOptions.CurrentTime", Field, 0},
 		{"VerifyOptions.DNSName", Field, 0},
 		{"VerifyOptions.Intermediates", Field, 0},
@@ -1975,6 +2076,8 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*File).DynString", Method, 1},
 		{"(*File).DynValue", Method, 21},
 		{"(*File).DynamicSymbols", Method, 4},
+		{"(*File).DynamicVersionNeeds", Method, 24},
+		{"(*File).DynamicVersions", Method, 24},
 		{"(*File).ImportedLibraries", Method, 0},
 		{"(*File).ImportedSymbols", Method, 0},
 		{"(*File).Section", Method, 0},
@@ -2240,6 +2343,19 @@ var PackageSymbols = map[string][]Symbol{
 		{"DynFlag", Type, 0},
 		{"DynFlag1", Type, 21},
 		{"DynTag", Type, 0},
+		{"DynamicVersion", Type, 24},
+		{"DynamicVersion.Deps", Field, 24},
+		{"DynamicVersion.Flags", Field, 24},
+		{"DynamicVersion.Index", Field, 24},
+		{"DynamicVersion.Name", Field, 24},
+		{"DynamicVersionDep", Type, 24},
+		{"DynamicVersionDep.Dep", Field, 24},
+		{"DynamicVersionDep.Flags", Field, 24},
+		{"DynamicVersionDep.Index", Field, 24},
+		{"DynamicVersionFlag", Type, 24},
+		{"DynamicVersionNeed", Type, 24},
+		{"DynamicVersionNeed.Name", Field, 24},
+		{"DynamicVersionNeed.Needs", Field, 24},
 		{"EI_ABIVERSION", Const, 0},
 		{"EI_CLASS", Const, 0},
 		{"EI_DATA", Const, 0},
@@ -3726,8 +3842,19 @@ var PackageSymbols = map[string][]Symbol{
 		{"Symbol.Size", Field, 0},
 		{"Symbol.Value", Field, 0},
 		{"Symbol.Version", Field, 13},
+		{"Symbol.VersionIndex", Field, 24},
+		{"Symbol.VersionScope", Field, 24},
+		{"SymbolVersionScope", Type, 24},
 		{"Type", Type, 0},
+		{"VER_FLG_BASE", Const, 24},
+		{"VER_FLG_INFO", Const, 24},
+		{"VER_FLG_WEAK", Const, 24},
 		{"Version", Type, 0},
+		{"VersionScopeGlobal", Const, 24},
+		{"VersionScopeHidden", Const, 24},
+		{"VersionScopeLocal", Const, 24},
+		{"VersionScopeNone", Const, 24},
+		{"VersionScopeSpecific", Const, 24},
 	},
 	"debug/gosym": {
 		{"(*DecodingError).Error", Method, 0},
@@ -4453,8 +4580,10 @@ var PackageSymbols = map[string][]Symbol{
 		{"FS", Type, 16},
 	},
 	"encoding": {
+		{"BinaryAppender", Type, 24},
 		{"BinaryMarshaler", Type, 2},
 		{"BinaryUnmarshaler", Type, 2},
+		{"TextAppender", Type, 24},
 		{"TextMarshaler", Type, 2},
 		{"TextUnmarshaler", Type, 2},
 	},
@@ -5984,13 +6113,16 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*Interface).Complete", Method, 5},
 		{"(*Interface).Embedded", Method, 5},
 		{"(*Interface).EmbeddedType", Method, 11},
+		{"(*Interface).EmbeddedTypes", Method, 24},
 		{"(*Interface).Empty", Method, 5},
 		{"(*Interface).ExplicitMethod", Method, 5},
+		{"(*Interface).ExplicitMethods", Method, 24},
 		{"(*Interface).IsComparable", Method, 18},
 		{"(*Interface).IsImplicit", Method, 18},
 		{"(*Interface).IsMethodSet", Method, 18},
 		{"(*Interface).MarkImplicit", Method, 18},
 		{"(*Interface).Method", Method, 5},
+		{"(*Interface).Methods", Method, 24},
 		{"(*Interface).NumEmbeddeds", Method, 5},
 		{"(*Interface).NumExplicitMethods", Method, 5},
 		{"(*Interface).NumMethods", Method, 5},
@@ -6011,9 +6143,11 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*MethodSet).At", Method, 5},
 		{"(*MethodSet).Len", Method, 5},
 		{"(*MethodSet).Lookup", Method, 5},
+		{"(*MethodSet).Methods", Method, 24},
 		{"(*MethodSet).String", Method, 5},
 		{"(*Named).AddMethod", Method, 5},
 		{"(*Named).Method", Method, 5},
+		{"(*Named).Methods", Method, 24},
 		{"(*Named).NumMethods", Method, 5},
 		{"(*Named).Obj", Method, 5},
 		{"(*Named).Origin", Method, 18},
@@ -6054,6 +6188,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*Pointer).String", Method, 5},
 		{"(*Pointer).Underlying", Method, 5},
 		{"(*Scope).Child", Method, 5},
+		{"(*Scope).Children", Method, 24},
 		{"(*Scope).Contains", Method, 5},
 		{"(*Scope).End", Method, 5},
 		{"(*Scope).Innermost", Method, 5},
@@ -6089,6 +6224,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*StdSizes).Offsetsof", Method, 5},
 		{"(*StdSizes).Sizeof", Method, 5},
 		{"(*Struct).Field", Method, 5},
+		{"(*Struct).Fields", Method, 24},
 		{"(*Struct).NumFields", Method, 5},
 		{"(*Struct).String", Method, 5},
 		{"(*Struct).Tag", Method, 5},
@@ -6100,8 +6236,10 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*Tuple).Len", Method, 5},
 		{"(*Tuple).String", Method, 5},
 		{"(*Tuple).Underlying", Method, 5},
+		{"(*Tuple).Variables", Method, 24},
 		{"(*TypeList).At", Method, 18},
 		{"(*TypeList).Len", Method, 18},
+		{"(*TypeList).Types", Method, 24},
 		{"(*TypeName).Exported", Method, 5},
 		{"(*TypeName).Id", Method, 5},
 		{"(*TypeName).IsAlias", Method, 9},
@@ -6119,9 +6257,11 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*TypeParam).Underlying", Method, 18},
 		{"(*TypeParamList).At", Method, 18},
 		{"(*TypeParamList).Len", Method, 18},
+		{"(*TypeParamList).TypeParams", Method, 24},
 		{"(*Union).Len", Method, 18},
 		{"(*Union).String", Method, 18},
 		{"(*Union).Term", Method, 18},
+		{"(*Union).Terms", Method, 24},
 		{"(*Union).Underlying", Method, 18},
 		{"(*Var).Anonymous", Method, 5},
 		{"(*Var).Embedded", Method, 11},
@@ -6392,10 +6532,12 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*Hash).WriteByte", Method, 14},
 		{"(*Hash).WriteString", Method, 14},
 		{"Bytes", Func, 19},
+		{"Comparable", Func, 24},
 		{"Hash", Type, 14},
 		{"MakeSeed", Func, 14},
 		{"Seed", Type, 14},
 		{"String", Func, 19},
+		{"WriteComparable", Func, 24},
 	},
 	"html": {
 		{"EscapeString", Func, 0},
@@ -7082,6 +7224,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*JSONHandler).WithGroup", Method, 21},
 		{"(*Level).UnmarshalJSON", Method, 21},
 		{"(*Level).UnmarshalText", Method, 21},
+		{"(*LevelVar).AppendText", Method, 24},
 		{"(*LevelVar).Level", Method, 21},
 		{"(*LevelVar).MarshalText", Method, 21},
 		{"(*LevelVar).Set", Method, 21},
@@ -7110,6 +7253,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"(Attr).Equal", Method, 21},
 		{"(Attr).String", Method, 21},
 		{"(Kind).String", Method, 21},
+		{"(Level).AppendText", Method, 24},
 		{"(Level).Level", Method, 21},
 		{"(Level).MarshalJSON", Method, 21},
 		{"(Level).MarshalText", Method, 21},
@@ -7140,6 +7284,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"Debug", Func, 21},
 		{"DebugContext", Func, 21},
 		{"Default", Func, 21},
+		{"DiscardHandler", Var, 24},
 		{"Duration", Func, 21},
 		{"DurationValue", Func, 21},
 		{"Error", Func, 21},
@@ -7375,6 +7520,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*Float).Acc", Method, 5},
 		{"(*Float).Add", Method, 5},
 		{"(*Float).Append", Method, 5},
+		{"(*Float).AppendText", Method, 24},
 		{"(*Float).Cmp", Method, 5},
 		{"(*Float).Copy", Method, 5},
 		{"(*Float).Float32", Method, 5},
@@ -7421,6 +7567,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*Int).And", Method, 0},
 		{"(*Int).AndNot", Method, 0},
 		{"(*Int).Append", Method, 6},
+		{"(*Int).AppendText", Method, 24},
 		{"(*Int).Binomial", Method, 0},
 		{"(*Int).Bit", Method, 0},
 		{"(*Int).BitLen", Method, 0},
@@ -7477,6 +7624,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*Int).Xor", Method, 0},
 		{"(*Rat).Abs", Method, 0},
 		{"(*Rat).Add", Method, 0},
+		{"(*Rat).AppendText", Method, 24},
 		{"(*Rat).Cmp", Method, 0},
 		{"(*Rat).Denom", Method, 0},
 		{"(*Rat).Float32", Method, 4},
@@ -7659,11 +7807,13 @@ var PackageSymbols = map[string][]Symbol{
 		{"Zipf", Type, 0},
 	},
 	"math/rand/v2": {
+		{"(*ChaCha8).AppendBinary", Method, 24},
 		{"(*ChaCha8).MarshalBinary", Method, 22},
 		{"(*ChaCha8).Read", Method, 23},
 		{"(*ChaCha8).Seed", Method, 22},
 		{"(*ChaCha8).Uint64", Method, 22},
 		{"(*ChaCha8).UnmarshalBinary", Method, 22},
+		{"(*PCG).AppendBinary", Method, 24},
 		{"(*PCG).MarshalBinary", Method, 22},
 		{"(*PCG).Seed", Method, 22},
 		{"(*PCG).Uint64", Method, 22},
@@ -7931,6 +8081,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*UnixListener).SyscallConn", Method, 10},
 		{"(Flags).String", Method, 0},
 		{"(HardwareAddr).String", Method, 0},
+		{"(IP).AppendText", Method, 24},
 		{"(IP).DefaultMask", Method, 0},
 		{"(IP).Equal", Method, 0},
 		{"(IP).IsGlobalUnicast", Method, 0},
@@ -8131,6 +8282,9 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*MaxBytesError).Error", Method, 19},
 		{"(*ProtocolError).Error", Method, 0},
 		{"(*ProtocolError).Is", Method, 21},
+		{"(*Protocols).SetHTTP1", Method, 24},
+		{"(*Protocols).SetHTTP2", Method, 24},
+		{"(*Protocols).SetUnencryptedHTTP2", Method, 24},
 		{"(*Request).AddCookie", Method, 0},
 		{"(*Request).BasicAuth", Method, 4},
 		{"(*Request).Clone", Method, 13},
@@ -8190,6 +8344,10 @@ var PackageSymbols = map[string][]Symbol{
 		{"(Header).Values", Method, 14},
 		{"(Header).Write", Method, 0},
 		{"(Header).WriteSubset", Method, 0},
+		{"(Protocols).HTTP1", Method, 24},
+		{"(Protocols).HTTP2", Method, 24},
+		{"(Protocols).String", Method, 24},
+		{"(Protocols).UnencryptedHTTP2", Method, 24},
 		{"AllowQuerySemicolons", Func, 17},
 		{"CanonicalHeaderKey", Func, 0},
 		{"Client", Type, 0},
@@ -8252,6 +8410,18 @@ var PackageSymbols = map[string][]Symbol{
 		{"FileSystem", Type, 0},
 		{"Flusher", Type, 0},
 		{"Get", Func, 0},
+		{"HTTP2Config", Type, 24},
+		{"HTTP2Config.CountError", Field, 24},
+		{"HTTP2Config.MaxConcurrentStreams", Field, 24},
+		{"HTTP2Config.MaxDecoderHeaderTableSize", Field, 24},
+		{"HTTP2Config.MaxEncoderHeaderTableSize", Field, 24},
+		{"HTTP2Config.MaxReadFrameSize", Field, 24},
+		{"HTTP2Config.MaxReceiveBufferPerConnection", Field, 24},
+		{"HTTP2Config.MaxReceiveBufferPerStream", Field, 24},
+		{"HTTP2Config.PermitProhibitedCipherSuites", Field, 24},
+		{"HTTP2Config.PingTimeout", Field, 24},
+		{"HTTP2Config.SendPingTimeout", Field, 24},
+		{"HTTP2Config.WriteByteTimeout", Field, 24},
 		{"Handle", Func, 0},
 		{"HandleFunc", Func, 0},
 		{"Handler", Type, 0},
@@ -8292,6 +8462,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"PostForm", Func, 0},
 		{"ProtocolError", Type, 0},
 		{"ProtocolError.ErrorString", Field, 0},
+		{"Protocols", Type, 24},
 		{"ProxyFromEnvironment", Func, 0},
 		{"ProxyURL", Func, 0},
 		{"PushOptions", Type, 8},
@@ -8361,9 +8532,11 @@ var PackageSymbols = map[string][]Symbol{
 		{"Server.ConnState", Field, 3},
 		{"Server.DisableGeneralOptionsHandler", Field, 20},
 		{"Server.ErrorLog", Field, 3},
+		{"Server.HTTP2", Field, 24},
 		{"Server.Handler", Field, 0},
 		{"Server.IdleTimeout", Field, 8},
 		{"Server.MaxHeaderBytes", Field, 0},
+		{"Server.Protocols", Field, 24},
 		{"Server.ReadHeaderTimeout", Field, 8},
 		{"Server.ReadTimeout", Field, 0},
 		{"Server.TLSConfig", Field, 0},
@@ -8453,12 +8626,14 @@ var PackageSymbols = map[string][]Symbol{
 		{"Transport.ExpectContinueTimeout", Field, 6},
 		{"Transport.ForceAttemptHTTP2", Field, 13},
 		{"Transport.GetProxyConnectHeader", Field, 16},
+		{"Transport.HTTP2", Field, 24},
 		{"Transport.IdleConnTimeout", Field, 7},
 		{"Transport.MaxConnsPerHost", Field, 11},
 		{"Transport.MaxIdleConns", Field, 7},
 		{"Transport.MaxIdleConnsPerHost", Field, 0},
 		{"Transport.MaxResponseHeaderBytes", Field, 7},
 		{"Transport.OnProxyConnectResponse", Field, 20},
+		{"Transport.Protocols", Field, 24},
 		{"Transport.Proxy", Field, 0},
 		{"Transport.ProxyConnectHeader", Field, 8},
 		{"Transport.ReadBufferSize", Field, 13},
@@ -8646,6 +8821,8 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*AddrPort).UnmarshalText", Method, 18},
 		{"(*Prefix).UnmarshalBinary", Method, 18},
 		{"(*Prefix).UnmarshalText", Method, 18},
+		{"(Addr).AppendBinary", Method, 24},
+		{"(Addr).AppendText", Method, 24},
 		{"(Addr).AppendTo", Method, 18},
 		{"(Addr).As16", Method, 18},
 		{"(Addr).As4", Method, 18},
@@ -8676,6 +8853,8 @@ var PackageSymbols = map[string][]Symbol{
 		{"(Addr).WithZone", Method, 18},
 		{"(Addr).Zone", Method, 18},
 		{"(AddrPort).Addr", Method, 18},
+		{"(AddrPort).AppendBinary", Method, 24},
+		{"(AddrPort).AppendText", Method, 24},
 		{"(AddrPort).AppendTo", Method, 18},
 		{"(AddrPort).Compare", Method, 22},
 		{"(AddrPort).IsValid", Method, 18},
@@ -8684,6 +8863,8 @@ var PackageSymbols = map[string][]Symbol{
 		{"(AddrPort).Port", Method, 18},
 		{"(AddrPort).String", Method, 18},
 		{"(Prefix).Addr", Method, 18},
+		{"(Prefix).AppendBinary", Method, 24},
+		{"(Prefix).AppendText", Method, 24},
 		{"(Prefix).AppendTo", Method, 18},
 		{"(Prefix).Bits", Method, 18},
 		{"(Prefix).Contains", Method, 18},
@@ -8868,6 +9049,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*Error).Temporary", Method, 6},
 		{"(*Error).Timeout", Method, 6},
 		{"(*Error).Unwrap", Method, 13},
+		{"(*URL).AppendBinary", Method, 24},
 		{"(*URL).EscapedFragment", Method, 15},
 		{"(*URL).EscapedPath", Method, 5},
 		{"(*URL).Hostname", Method, 8},
@@ -8967,6 +9149,17 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*ProcessState).SysUsage", Method, 0},
 		{"(*ProcessState).SystemTime", Method, 0},
 		{"(*ProcessState).UserTime", Method, 0},
+		{"(*Root).Close", Method, 24},
+		{"(*Root).Create", Method, 24},
+		{"(*Root).FS", Method, 24},
+		{"(*Root).Lstat", Method, 24},
+		{"(*Root).Mkdir", Method, 24},
+		{"(*Root).Name", Method, 24},
+		{"(*Root).Open", Method, 24},
+		{"(*Root).OpenFile", Method, 24},
+		{"(*Root).OpenRoot", Method, 24},
+		{"(*Root).Remove", Method, 24},
+		{"(*Root).Stat", Method, 24},
 		{"(*SyscallError).Error", Method, 0},
 		{"(*SyscallError).Timeout", Method, 10},
 		{"(*SyscallError).Unwrap", Method, 13},
@@ -9060,6 +9253,8 @@ var PackageSymbols = map[string][]Symbol{
 		{"O_WRONLY", Const, 0},
 		{"Open", Func, 0},
 		{"OpenFile", Func, 0},
+		{"OpenInRoot", Func, 24},
+		{"OpenRoot", Func, 24},
 		{"PathError", Type, 0},
 		{"PathError.Err", Field, 0},
 		{"PathError.Op", Field, 0},
@@ -9081,6 +9276,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"Remove", Func, 0},
 		{"RemoveAll", Func, 0},
 		{"Rename", Func, 0},
+		{"Root", Type, 24},
 		{"SEEK_CUR", Const, 0},
 		{"SEEK_END", Const, 0},
 		{"SEEK_SET", Const, 0},
@@ -9422,6 +9618,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"Zero", Func, 0},
 	},
 	"regexp": {
+		{"(*Regexp).AppendText", Method, 24},
 		{"(*Regexp).Copy", Method, 6},
 		{"(*Regexp).Expand", Method, 0},
 		{"(*Regexp).ExpandString", Method, 0},
@@ -9602,6 +9799,8 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*StackRecord).Stack", Method, 0},
 		{"(*TypeAssertionError).Error", Method, 0},
 		{"(*TypeAssertionError).RuntimeError", Method, 0},
+		{"(Cleanup).Stop", Method, 24},
+		{"AddCleanup", Func, 24},
 		{"BlockProfile", Func, 1},
 		{"BlockProfileRecord", Type, 1},
 		{"BlockProfileRecord.Count", Field, 1},
@@ -9612,6 +9811,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"Caller", Func, 0},
 		{"Callers", Func, 0},
 		{"CallersFrames", Func, 7},
+		{"Cleanup", Type, 24},
 		{"Compiler", Const, 0},
 		{"Error", Type, 0},
 		{"Frame", Type, 7},
@@ -9974,6 +10174,8 @@ var PackageSymbols = map[string][]Symbol{
 		{"EqualFold", Func, 0},
 		{"Fields", Func, 0},
 		{"FieldsFunc", Func, 0},
+		{"FieldsFuncSeq", Func, 24},
+		{"FieldsSeq", Func, 24},
 		{"HasPrefix", Func, 0},
 		{"HasSuffix", Func, 0},
 		{"Index", Func, 0},
@@ -9986,6 +10188,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"LastIndexAny", Func, 0},
 		{"LastIndexByte", Func, 5},
 		{"LastIndexFunc", Func, 0},
+		{"Lines", Func, 24},
 		{"Map", Func, 0},
 		{"NewReader", Func, 0},
 		{"NewReplacer", Func, 0},
@@ -9997,7 +10200,9 @@ var PackageSymbols = map[string][]Symbol{
 		{"Split", Func, 0},
 		{"SplitAfter", Func, 0},
 		{"SplitAfterN", Func, 0},
+		{"SplitAfterSeq", Func, 24},
 		{"SplitN", Func, 0},
+		{"SplitSeq", Func, 24},
 		{"Title", Func, 0},
 		{"ToLower", Func, 0},
 		{"ToLowerSpecial", Func, 0},
@@ -16413,7 +16618,9 @@ var PackageSymbols = map[string][]Symbol{
 		{"ValueOf", Func, 0},
 	},
 	"testing": {
+		{"(*B).Chdir", Method, 24},
 		{"(*B).Cleanup", Method, 14},
+		{"(*B).Context", Method, 24},
 		{"(*B).Elapsed", Method, 20},
 		{"(*B).Error", Method, 0},
 		{"(*B).Errorf", Method, 0},
@@ -16425,6 +16632,7 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*B).Helper", Method, 9},
 		{"(*B).Log", Method, 0},
 		{"(*B).Logf", Method, 0},
+		{"(*B).Loop", Method, 24},
 		{"(*B).Name", Method, 8},
 		{"(*B).ReportAllocs", Method, 1},
 		{"(*B).ReportMetric", Method, 13},
@@ -16442,7 +16650,9 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*B).StopTimer", Method, 0},
 		{"(*B).TempDir", Method, 15},
 		{"(*F).Add", Method, 18},
+		{"(*F).Chdir", Method, 24},
 		{"(*F).Cleanup", Method, 18},
+		{"(*F).Context", Method, 24},
 		{"(*F).Error", Method, 18},
 		{"(*F).Errorf", Method, 18},
 		{"(*F).Fail", Method, 18},
@@ -16463,7 +16673,9 @@ var PackageSymbols = map[string][]Symbol{
 		{"(*F).TempDir", Method, 18},
 		{"(*M).Run", Method, 4},
 		{"(*PB).Next", Method, 3},
+		{"(*T).Chdir", Method, 24},
 		{"(*T).Cleanup", Method, 14},
+		{"(*T).Context", Method, 24},
 		{"(*T).Deadline", Method, 15},
 		{"(*T).Error", Method, 0},
 		{"(*T).Errorf", Method, 0},
@@ -16954,7 +17166,9 @@ var PackageSymbols = map[string][]Symbol{
 		{"(Time).Add", Method, 0},
 		{"(Time).AddDate", Method, 0},
 		{"(Time).After", Method, 0},
+		{"(Time).AppendBinary", Method, 24},
 		{"(Time).AppendFormat", Method, 5},
+		{"(Time).AppendText", Method, 24},
 		{"(Time).Before", Method, 0},
 		{"(Time).Clock", Method, 0},
 		{"(Time).Compare", Method, 20},
@@ -17428,4 +17642,9 @@ var PackageSymbols = map[string][]Symbol{
 		{"String", Func, 0},
 		{"StringData", Func, 0},
 	},
+	"weak": {
+		{"(Pointer).Value", Method, 24},
+		{"Make", Func, 24},
+		{"Pointer", Type, 24},
+	},
 }
diff --git a/vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go b/vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go
deleted file mode 100644
index ff9437a36c..0000000000
--- a/vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright 2023 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// package tokeninternal provides access to some internal features of the token
-// package.
-package tokeninternal
-
-import (
-	"fmt"
-	"go/token"
-	"sort"
-	"sync"
-	"unsafe"
-)
-
-// GetLines returns the table of line-start offsets from a token.File.
-func GetLines(file *token.File) []int {
-	// token.File has a Lines method on Go 1.21 and later.
-	if file, ok := (interface{})(file).(interface{ Lines() []int }); ok {
-		return file.Lines()
-	}
-
-	// This declaration must match that of token.File.
-	// This creates a risk of dependency skew.
-	// For now we check that the size of the two
-	// declarations is the same, on the (fragile) assumption
-	// that future changes would add fields.
-	type tokenFile119 struct {
-		_     string
-		_     int
-		_     int
-		mu    sync.Mutex // we're not complete monsters
-		lines []int
-		_     []struct{}
-	}
-
-	if unsafe.Sizeof(*file) != unsafe.Sizeof(tokenFile119{}) {
-		panic("unexpected token.File size")
-	}
-	var ptr *tokenFile119
-	type uP = unsafe.Pointer
-	*(*uP)(uP(&ptr)) = uP(file)
-	ptr.mu.Lock()
-	defer ptr.mu.Unlock()
-	return ptr.lines
-}
-
-// AddExistingFiles adds the specified files to the FileSet if they
-// are not already present. It panics if any pair of files in the
-// resulting FileSet would overlap.
-func AddExistingFiles(fset *token.FileSet, files []*token.File) {
-	// Punch through the FileSet encapsulation.
-	type tokenFileSet struct {
-		// This type remained essentially consistent from go1.16 to go1.21.
-		mutex sync.RWMutex
-		base  int
-		files []*token.File
-		_     *token.File // changed to atomic.Pointer[token.File] in go1.19
-	}
-
-	// If the size of token.FileSet changes, this will fail to compile.
-	const delta = int64(unsafe.Sizeof(tokenFileSet{})) - int64(unsafe.Sizeof(token.FileSet{}))
-	var _ [-delta * delta]int
-
-	type uP = unsafe.Pointer
-	var ptr *tokenFileSet
-	*(*uP)(uP(&ptr)) = uP(fset)
-	ptr.mutex.Lock()
-	defer ptr.mutex.Unlock()
-
-	// Merge and sort.
-	newFiles := append(ptr.files, files...)
-	sort.Slice(newFiles, func(i, j int) bool {
-		return newFiles[i].Base() < newFiles[j].Base()
-	})
-
-	// Reject overlapping files.
-	// Discard adjacent identical files.
-	out := newFiles[:0]
-	for i, file := range newFiles {
-		if i > 0 {
-			prev := newFiles[i-1]
-			if file == prev {
-				continue
-			}
-			if prev.Base()+prev.Size()+1 > file.Base() {
-				panic(fmt.Sprintf("file %s (%d-%d) overlaps with file %s (%d-%d)",
-					prev.Name(), prev.Base(), prev.Base()+prev.Size(),
-					file.Name(), file.Base(), file.Base()+file.Size()))
-			}
-		}
-		out = append(out, file)
-	}
-	newFiles = out
-
-	ptr.files = newFiles
-
-	// Advance FileSet.Base().
-	if len(newFiles) > 0 {
-		last := newFiles[len(newFiles)-1]
-		newBase := last.Base() + last.Size() + 1
-		if ptr.base < newBase {
-			ptr.base = newBase
-		}
-	}
-}
-
-// FileSetFor returns a new FileSet containing a sequence of new Files with
-// the same base, size, and line as the input files, for use in APIs that
-// require a FileSet.
-//
-// Precondition: the input files must be non-overlapping, and sorted in order
-// of their Base.
-func FileSetFor(files ...*token.File) *token.FileSet {
-	fset := token.NewFileSet()
-	for _, f := range files {
-		f2 := fset.AddFile(f.Name(), f.Base(), f.Size())
-		lines := GetLines(f)
-		f2.SetLines(lines)
-	}
-	return fset
-}
-
-// CloneFileSet creates a new FileSet holding all files in fset. It does not
-// create copies of the token.Files in fset: they are added to the resulting
-// FileSet unmodified.
-func CloneFileSet(fset *token.FileSet) *token.FileSet {
-	var files []*token.File
-	fset.Iterate(func(f *token.File) bool {
-		files = append(files, f)
-		return true
-	})
-	newFileSet := token.NewFileSet()
-	AddExistingFiles(newFileSet, files)
-	return newFileSet
-}
diff --git a/vendor/golang.org/x/tools/internal/typeparams/common.go b/vendor/golang.org/x/tools/internal/typeparams/common.go
new file mode 100644
index 0000000000..cdae2b8e81
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/typeparams/common.go
@@ -0,0 +1,68 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package typeparams contains common utilities for writing tools that
+// interact with generic Go code, as introduced with Go 1.18. It
+// supplements the standard library APIs. Notably, the StructuralTerms
+// API computes a minimal representation of the structural
+// restrictions on a type parameter.
+//
+// An external version of these APIs is available in the
+// golang.org/x/exp/typeparams module.
+package typeparams
+
+import (
+	"go/ast"
+	"go/token"
+	"go/types"
+)
+
+// UnpackIndexExpr extracts data from AST nodes that represent index
+// expressions.
+//
+// For an ast.IndexExpr, the resulting indices slice will contain exactly one
+// index expression. For an ast.IndexListExpr (go1.18+), it may have a variable
+// number of index expressions.
+//
+// For nodes that don't represent index expressions, the first return value of
+// UnpackIndexExpr will be nil.
+func UnpackIndexExpr(n ast.Node) (x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) {
+	switch e := n.(type) {
+	case *ast.IndexExpr:
+		return e.X, e.Lbrack, []ast.Expr{e.Index}, e.Rbrack
+	case *ast.IndexListExpr:
+		return e.X, e.Lbrack, e.Indices, e.Rbrack
+	}
+	return nil, token.NoPos, nil, token.NoPos
+}
+
+// PackIndexExpr returns an *ast.IndexExpr or *ast.IndexListExpr, depending on
+// the cardinality of indices. Calling PackIndexExpr with len(indices) == 0
+// will panic.
+func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) ast.Expr {
+	switch len(indices) {
+	case 0:
+		panic("empty indices")
+	case 1:
+		return &ast.IndexExpr{
+			X:      x,
+			Lbrack: lbrack,
+			Index:  indices[0],
+			Rbrack: rbrack,
+		}
+	default:
+		return &ast.IndexListExpr{
+			X:       x,
+			Lbrack:  lbrack,
+			Indices: indices,
+			Rbrack:  rbrack,
+		}
+	}
+}
+
+// IsTypeParam reports whether t is a type parameter (or an alias of one).
+func IsTypeParam(t types.Type) bool {
+	_, ok := types.Unalias(t).(*types.TypeParam)
+	return ok
+}
diff --git a/vendor/golang.org/x/tools/internal/typeparams/coretype.go b/vendor/golang.org/x/tools/internal/typeparams/coretype.go
new file mode 100644
index 0000000000..27a2b17929
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/typeparams/coretype.go
@@ -0,0 +1,155 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package typeparams
+
+import (
+	"fmt"
+	"go/types"
+)
+
+// CoreType returns the core type of T or nil if T does not have a core type.
+//
+// See https://go.dev/ref/spec#Core_types for the definition of a core type.
+func CoreType(T types.Type) types.Type {
+	U := T.Underlying()
+	if _, ok := U.(*types.Interface); !ok {
+		return U // for non-interface types,
+	}
+
+	terms, err := NormalTerms(U)
+	if len(terms) == 0 || err != nil {
+		// len(terms) -> empty type set of interface.
+		// err != nil => U is invalid, exceeds complexity bounds, or has an empty type set.
+		return nil // no core type.
+	}
+
+	U = terms[0].Type().Underlying()
+	var identical int // i in [0,identical) => Identical(U, terms[i].Type().Underlying())
+	for identical = 1; identical < len(terms); identical++ {
+		if !types.Identical(U, terms[identical].Type().Underlying()) {
+			break
+		}
+	}
+
+	if identical == len(terms) {
+		// https://go.dev/ref/spec#Core_types
+		// "There is a single type U which is the underlying type of all types in the type set of T"
+		return U
+	}
+	ch, ok := U.(*types.Chan)
+	if !ok {
+		return nil // no core type as identical < len(terms) and U is not a channel.
+	}
+	// https://go.dev/ref/spec#Core_types
+	// "the type chan E if T contains only bidirectional channels, or the type chan<- E or
+	// <-chan E depending on the direction of the directional channels present."
+	for chans := identical; chans < len(terms); chans++ {
+		curr, ok := terms[chans].Type().Underlying().(*types.Chan)
+		if !ok {
+			return nil
+		}
+		if !types.Identical(ch.Elem(), curr.Elem()) {
+			return nil // channel elements are not identical.
+		}
+		if ch.Dir() == types.SendRecv {
+			// ch is bidirectional. We can safely always use curr's direction.
+			ch = curr
+		} else if curr.Dir() != types.SendRecv && ch.Dir() != curr.Dir() {
+			// ch and curr are not bidirectional and not the same direction.
+			return nil
+		}
+	}
+	return ch
+}
+
+// NormalTerms returns a slice of terms representing the normalized structural
+// type restrictions of a type, if any.
+//
+// For all types other than *types.TypeParam, *types.Interface, and
+// *types.Union, this is just a single term with Tilde() == false and
+// Type() == typ. For *types.TypeParam, *types.Interface, and *types.Union, see
+// below.
+//
+// Structural type restrictions of a type parameter are created via
+// non-interface types embedded in its constraint interface (directly, or via a
+// chain of interface embeddings). For example, in the declaration type
+// T[P interface{~int; m()}] int the structural restriction of the type
+// parameter P is ~int.
+//
+// With interface embedding and unions, the specification of structural type
+// restrictions may be arbitrarily complex. For example, consider the
+// following:
+//
+//	type A interface{ ~string|~[]byte }
+//
+//	type B interface{ int|string }
+//
+//	type C interface { ~string|~int }
+//
+//	type T[P interface{ A|B; C }] int
+//
+// In this example, the structural type restriction of P is ~string|int: A|B
+// expands to ~string|~[]byte|int|string, which reduces to ~string|~[]byte|int,
+// which when intersected with C (~string|~int) yields ~string|int.
+//
+// NormalTerms computes these expansions and reductions, producing a
+// "normalized" form of the embeddings. A structural restriction is normalized
+// if it is a single union containing no interface terms, and is minimal in the
+// sense that removing any term changes the set of types satisfying the
+// constraint. It is left as a proof for the reader that, modulo sorting, there
+// is exactly one such normalized form.
+//
+// Because the minimal representation always takes this form, NormalTerms
+// returns a slice of tilde terms corresponding to the terms of the union in
+// the normalized structural restriction. An error is returned if the type is
+// invalid, exceeds complexity bounds, or has an empty type set. In the latter
+// case, NormalTerms returns ErrEmptyTypeSet.
+//
+// NormalTerms makes no guarantees about the order of terms, except that it
+// is deterministic.
+func NormalTerms(T types.Type) ([]*types.Term, error) {
+	// typeSetOf(T) == typeSetOf(Unalias(T))
+	typ := types.Unalias(T)
+	if named, ok := typ.(*types.Named); ok {
+		typ = named.Underlying()
+	}
+	switch typ := typ.(type) {
+	case *types.TypeParam:
+		return StructuralTerms(typ)
+	case *types.Union:
+		return UnionTermSet(typ)
+	case *types.Interface:
+		return InterfaceTermSet(typ)
+	default:
+		return []*types.Term{types.NewTerm(false, T)}, nil
+	}
+}
+
+// Deref returns the type of the variable pointed to by t,
+// if t's core type is a pointer; otherwise it returns t.
+//
+// Do not assume that Deref(T)==T implies T is not a pointer:
+// consider "type T *T", for example.
+//
+// TODO(adonovan): ideally this would live in typesinternal, but that
+// creates an import cycle. Move there when we melt this package down.
+func Deref(t types.Type) types.Type {
+	if ptr, ok := CoreType(t).(*types.Pointer); ok {
+		return ptr.Elem()
+	}
+	return t
+}
+
+// MustDeref returns the type of the variable pointed to by t.
+// It panics if t's core type is not a pointer.
+//
+// TODO(adonovan): ideally this would live in typesinternal, but that
+// creates an import cycle. Move there when we melt this package down.
+func MustDeref(t types.Type) types.Type {
+	if ptr, ok := CoreType(t).(*types.Pointer); ok {
+		return ptr.Elem()
+	}
+	panic(fmt.Sprintf("%v is not a pointer", t))
+}
diff --git a/vendor/golang.org/x/tools/internal/typeparams/free.go b/vendor/golang.org/x/tools/internal/typeparams/free.go
new file mode 100644
index 0000000000..0ade5c2949
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/typeparams/free.go
@@ -0,0 +1,131 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package typeparams
+
+import (
+	"go/types"
+
+	"golang.org/x/tools/internal/aliases"
+)
+
+// Free is a memoization of the set of free type parameters within a
+// type. It makes a sequence of calls to [Free.Has] for overlapping
+// types more efficient. The zero value is ready for use.
+//
+// NOTE: Adapted from go/types/infer.go. If it is later exported, factor.
+type Free struct {
+	seen map[types.Type]bool
+}
+
+// Has reports whether the specified type has a free type parameter.
+func (w *Free) Has(typ types.Type) (res bool) {
+	// detect cycles
+	if x, ok := w.seen[typ]; ok {
+		return x
+	}
+	if w.seen == nil {
+		w.seen = make(map[types.Type]bool)
+	}
+	w.seen[typ] = false
+	defer func() {
+		w.seen[typ] = res
+	}()
+
+	switch t := typ.(type) {
+	case nil, *types.Basic: // TODO(gri) should nil be handled here?
+		break
+
+	case *types.Alias:
+		if aliases.TypeParams(t).Len() > aliases.TypeArgs(t).Len() {
+			return true // This is an uninstantiated Alias.
+		}
+		// The expansion of an alias can have free type parameters,
+		// whether or not the alias itself has type parameters:
+		//
+		//   func _[K comparable]() {
+		//     type Set      = map[K]bool // free(Set)      = {K}
+		//     type MapTo[V] = map[K]V    // free(Map[foo]) = {V}
+		//   }
+		//
+		// So, we must Unalias.
+		return w.Has(types.Unalias(t))
+
+	case *types.Array:
+		return w.Has(t.Elem())
+
+	case *types.Slice:
+		return w.Has(t.Elem())
+
+	case *types.Struct:
+		for i, n := 0, t.NumFields(); i < n; i++ {
+			if w.Has(t.Field(i).Type()) {
+				return true
+			}
+		}
+
+	case *types.Pointer:
+		return w.Has(t.Elem())
+
+	case *types.Tuple:
+		n := t.Len()
+		for i := 0; i < n; i++ {
+			if w.Has(t.At(i).Type()) {
+				return true
+			}
+		}
+
+	case *types.Signature:
+		// t.tparams may not be nil if we are looking at a signature
+		// of a generic function type (or an interface method) that is
+		// part of the type we're testing. We don't care about these type
+		// parameters.
+		// Similarly, the receiver of a method may declare (rather than
+		// use) type parameters, we don't care about those either.
+		// Thus, we only need to look at the input and result parameters.
+		return w.Has(t.Params()) || w.Has(t.Results())
+
+	case *types.Interface:
+		for i, n := 0, t.NumMethods(); i < n; i++ {
+			if w.Has(t.Method(i).Type()) {
+				return true
+			}
+		}
+		terms, err := InterfaceTermSet(t)
+		if err != nil {
+			return false // ill typed
+		}
+		for _, term := range terms {
+			if w.Has(term.Type()) {
+				return true
+			}
+		}
+
+	case *types.Map:
+		return w.Has(t.Key()) || w.Has(t.Elem())
+
+	case *types.Chan:
+		return w.Has(t.Elem())
+
+	case *types.Named:
+		args := t.TypeArgs()
+		if params := t.TypeParams(); params.Len() > args.Len() {
+			return true // this is an uninstantiated named type.
+		}
+		for i, n := 0, args.Len(); i < n; i++ {
+			if w.Has(args.At(i)) {
+				return true
+			}
+		}
+		return w.Has(t.Underlying()) // recurse for types local to parameterized functions
+
+	case *types.TypeParam:
+		return true
+
+	default:
+		panic(t) // unreachable
+	}
+
+	return false
+}
diff --git a/vendor/golang.org/x/tools/internal/typeparams/normalize.go b/vendor/golang.org/x/tools/internal/typeparams/normalize.go
new file mode 100644
index 0000000000..93c80fdc96
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/typeparams/normalize.go
@@ -0,0 +1,218 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package typeparams
+
+import (
+	"errors"
+	"fmt"
+	"go/types"
+	"os"
+	"strings"
+)
+
+//go:generate go run copytermlist.go
+
+const debug = false
+
+var ErrEmptyTypeSet = errors.New("empty type set")
+
+// StructuralTerms returns a slice of terms representing the normalized
+// structural type restrictions of a type parameter, if any.
+//
+// Structural type restrictions of a type parameter are created via
+// non-interface types embedded in its constraint interface (directly, or via a
+// chain of interface embeddings). For example, in the declaration
+//
+//	type T[P interface{~int; m()}] int
+//
+// the structural restriction of the type parameter P is ~int.
+//
+// With interface embedding and unions, the specification of structural type
+// restrictions may be arbitrarily complex. For example, consider the
+// following:
+//
+//	type A interface{ ~string|~[]byte }
+//
+//	type B interface{ int|string }
+//
+//	type C interface { ~string|~int }
+//
+//	type T[P interface{ A|B; C }] int
+//
+// In this example, the structural type restriction of P is ~string|int: A|B
+// expands to ~string|~[]byte|int|string, which reduces to ~string|~[]byte|int,
+// which when intersected with C (~string|~int) yields ~string|int.
+//
+// StructuralTerms computes these expansions and reductions, producing a
+// "normalized" form of the embeddings. A structural restriction is normalized
+// if it is a single union containing no interface terms, and is minimal in the
+// sense that removing any term changes the set of types satisfying the
+// constraint. It is left as a proof for the reader that, modulo sorting, there
+// is exactly one such normalized form.
+//
+// Because the minimal representation always takes this form, StructuralTerms
+// returns a slice of tilde terms corresponding to the terms of the union in
+// the normalized structural restriction. An error is returned if the
+// constraint interface is invalid, exceeds complexity bounds, or has an empty
+// type set. In the latter case, StructuralTerms returns ErrEmptyTypeSet.
+//
+// StructuralTerms makes no guarantees about the order of terms, except that it
+// is deterministic.
+func StructuralTerms(tparam *types.TypeParam) ([]*types.Term, error) {
+	constraint := tparam.Constraint()
+	if constraint == nil {
+		return nil, fmt.Errorf("%s has nil constraint", tparam)
+	}
+	iface, _ := constraint.Underlying().(*types.Interface)
+	if iface == nil {
+		return nil, fmt.Errorf("constraint is %T, not *types.Interface", constraint.Underlying())
+	}
+	return InterfaceTermSet(iface)
+}
+
+// InterfaceTermSet computes the normalized terms for a constraint interface,
+// returning an error if the term set cannot be computed or is empty. In the
+// latter case, the error will be ErrEmptyTypeSet.
+//
+// See the documentation of StructuralTerms for more information on
+// normalization.
+func InterfaceTermSet(iface *types.Interface) ([]*types.Term, error) {
+	return computeTermSet(iface)
+}
+
+// UnionTermSet computes the normalized terms for a union, returning an error
+// if the term set cannot be computed or is empty. In the latter case, the
+// error will be ErrEmptyTypeSet.
+//
+// See the documentation of StructuralTerms for more information on
+// normalization.
+func UnionTermSet(union *types.Union) ([]*types.Term, error) {
+	return computeTermSet(union)
+}
+
+func computeTermSet(typ types.Type) ([]*types.Term, error) {
+	tset, err := computeTermSetInternal(typ, make(map[types.Type]*termSet), 0)
+	if err != nil {
+		return nil, err
+	}
+	if tset.terms.isEmpty() {
+		return nil, ErrEmptyTypeSet
+	}
+	if tset.terms.isAll() {
+		return nil, nil
+	}
+	var terms []*types.Term
+	for _, term := range tset.terms {
+		terms = append(terms, types.NewTerm(term.tilde, term.typ))
+	}
+	return terms, nil
+}
+
+// A termSet holds the normalized set of terms for a given type.
+//
+// The name termSet is intentionally distinct from 'type set': a type set is
+// all types that implement a type (and includes method restrictions), whereas
+// a term set just represents the structural restrictions on a type.
+type termSet struct {
+	complete bool
+	terms    termlist
+}
+
+func indentf(depth int, format string, args ...interface{}) {
+	fmt.Fprintf(os.Stderr, strings.Repeat(".", depth)+format+"\n", args...)
+}
+
+func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth int) (res *termSet, err error) {
+	if t == nil {
+		panic("nil type")
+	}
+
+	if debug {
+		indentf(depth, "%s", t.String())
+		defer func() {
+			if err != nil {
+				indentf(depth, "=> %s", err)
+			} else {
+				indentf(depth, "=> %s", res.terms.String())
+			}
+		}()
+	}
+
+	const maxTermCount = 100
+	if tset, ok := seen[t]; ok {
+		if !tset.complete {
+			return nil, fmt.Errorf("cycle detected in the declaration of %s", t)
+		}
+		return tset, nil
+	}
+
+	// Mark the current type as seen to avoid infinite recursion.
+	tset := new(termSet)
+	defer func() {
+		tset.complete = true
+	}()
+	seen[t] = tset
+
+	switch u := t.Underlying().(type) {
+	case *types.Interface:
+		// The term set of an interface is the intersection of the term sets of its
+		// embedded types.
+		tset.terms = allTermlist
+		for i := 0; i < u.NumEmbeddeds(); i++ {
+			embedded := u.EmbeddedType(i)
+			if _, ok := embedded.Underlying().(*types.TypeParam); ok {
+				return nil, fmt.Errorf("invalid embedded type %T", embedded)
+			}
+			tset2, err := computeTermSetInternal(embedded, seen, depth+1)
+			if err != nil {
+				return nil, err
+			}
+			tset.terms = tset.terms.intersect(tset2.terms)
+		}
+	case *types.Union:
+		// The term set of a union is the union of term sets of its terms.
+		tset.terms = nil
+		for i := 0; i < u.Len(); i++ {
+			t := u.Term(i)
+			var terms termlist
+			switch t.Type().Underlying().(type) {
+			case *types.Interface:
+				tset2, err := computeTermSetInternal(t.Type(), seen, depth+1)
+				if err != nil {
+					return nil, err
+				}
+				terms = tset2.terms
+			case *types.TypeParam, *types.Union:
+				// A stand-alone type parameter or union is not permitted as union
+				// term.
+				return nil, fmt.Errorf("invalid union term %T", t)
+			default:
+				if t.Type() == types.Typ[types.Invalid] {
+					continue
+				}
+				terms = termlist{{t.Tilde(), t.Type()}}
+			}
+			tset.terms = tset.terms.union(terms)
+			if len(tset.terms) > maxTermCount {
+				return nil, fmt.Errorf("exceeded max term count %d", maxTermCount)
+			}
+		}
+	case *types.TypeParam:
+		panic("unreachable")
+	default:
+		// For all other types, the term set is just a single non-tilde term
+		// holding the type itself.
+		if u != types.Typ[types.Invalid] {
+			tset.terms = termlist{{false, t}}
+		}
+	}
+	return tset, nil
+}
+
+// under is a facade for the go/types internal function of the same name. It is
+// used by typeterm.go.
+func under(t types.Type) types.Type {
+	return t.Underlying()
+}
diff --git a/vendor/golang.org/x/tools/internal/typeparams/termlist.go b/vendor/golang.org/x/tools/internal/typeparams/termlist.go
new file mode 100644
index 0000000000..cbd12f8013
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/typeparams/termlist.go
@@ -0,0 +1,163 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Code generated by copytermlist.go DO NOT EDIT.
+
+package typeparams
+
+import (
+	"bytes"
+	"go/types"
+)
+
+// A termlist represents the type set represented by the union
+// t1 ∪ y2 ∪ ... tn of the type sets of the terms t1 to tn.
+// A termlist is in normal form if all terms are disjoint.
+// termlist operations don't require the operands to be in
+// normal form.
+type termlist []*term
+
+// allTermlist represents the set of all types.
+// It is in normal form.
+var allTermlist = termlist{new(term)}
+
+// String prints the termlist exactly (without normalization).
+func (xl termlist) String() string {
+	if len(xl) == 0 {
+		return "∅"
+	}
+	var buf bytes.Buffer
+	for i, x := range xl {
+		if i > 0 {
+			buf.WriteString(" | ")
+		}
+		buf.WriteString(x.String())
+	}
+	return buf.String()
+}
+
+// isEmpty reports whether the termlist xl represents the empty set of types.
+func (xl termlist) isEmpty() bool {
+	// If there's a non-nil term, the entire list is not empty.
+	// If the termlist is in normal form, this requires at most
+	// one iteration.
+	for _, x := range xl {
+		if x != nil {
+			return false
+		}
+	}
+	return true
+}
+
+// isAll reports whether the termlist xl represents the set of all types.
+func (xl termlist) isAll() bool {
+	// If there's a 𝓤 term, the entire list is 𝓤.
+	// If the termlist is in normal form, this requires at most
+	// one iteration.
+	for _, x := range xl {
+		if x != nil && x.typ == nil {
+			return true
+		}
+	}
+	return false
+}
+
+// norm returns the normal form of xl.
+func (xl termlist) norm() termlist {
+	// Quadratic algorithm, but good enough for now.
+	// TODO(gri) fix asymptotic performance
+	used := make([]bool, len(xl))
+	var rl termlist
+	for i, xi := range xl {
+		if xi == nil || used[i] {
+			continue
+		}
+		for j := i + 1; j < len(xl); j++ {
+			xj := xl[j]
+			if xj == nil || used[j] {
+				continue
+			}
+			if u1, u2 := xi.union(xj); u2 == nil {
+				// If we encounter a 𝓤 term, the entire list is 𝓤.
+				// Exit early.
+				// (Note that this is not just an optimization;
+				// if we continue, we may end up with a 𝓤 term
+				// and other terms and the result would not be
+				// in normal form.)
+				if u1.typ == nil {
+					return allTermlist
+				}
+				xi = u1
+				used[j] = true // xj is now unioned into xi - ignore it in future iterations
+			}
+		}
+		rl = append(rl, xi)
+	}
+	return rl
+}
+
+// union returns the union xl ∪ yl.
+func (xl termlist) union(yl termlist) termlist {
+	return append(xl, yl...).norm()
+}
+
+// intersect returns the intersection xl ∩ yl.
+func (xl termlist) intersect(yl termlist) termlist {
+	if xl.isEmpty() || yl.isEmpty() {
+		return nil
+	}
+
+	// Quadratic algorithm, but good enough for now.
+	// TODO(gri) fix asymptotic performance
+	var rl termlist
+	for _, x := range xl {
+		for _, y := range yl {
+			if r := x.intersect(y); r != nil {
+				rl = append(rl, r)
+			}
+		}
+	}
+	return rl.norm()
+}
+
+// equal reports whether xl and yl represent the same type set.
+func (xl termlist) equal(yl termlist) bool {
+	// TODO(gri) this should be more efficient
+	return xl.subsetOf(yl) && yl.subsetOf(xl)
+}
+
+// includes reports whether t ∈ xl.
+func (xl termlist) includes(t types.Type) bool {
+	for _, x := range xl {
+		if x.includes(t) {
+			return true
+		}
+	}
+	return false
+}
+
+// supersetOf reports whether y ⊆ xl.
+func (xl termlist) supersetOf(y *term) bool {
+	for _, x := range xl {
+		if y.subsetOf(x) {
+			return true
+		}
+	}
+	return false
+}
+
+// subsetOf reports whether xl ⊆ yl.
+func (xl termlist) subsetOf(yl termlist) bool {
+	if yl.isEmpty() {
+		return xl.isEmpty()
+	}
+
+	// each term x of xl must be a subset of yl
+	for _, x := range xl {
+		if !yl.supersetOf(x) {
+			return false // x is not a subset yl
+		}
+	}
+	return true
+}
diff --git a/vendor/golang.org/x/tools/internal/typeparams/typeterm.go b/vendor/golang.org/x/tools/internal/typeparams/typeterm.go
new file mode 100644
index 0000000000..7350bb702a
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/typeparams/typeterm.go
@@ -0,0 +1,169 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Code generated by copytermlist.go DO NOT EDIT.
+
+package typeparams
+
+import "go/types"
+
+// A term describes elementary type sets:
+//
+//	 ∅:  (*term)(nil)     == ∅                      // set of no types (empty set)
+//	 𝓤:  &term{}          == 𝓤                      // set of all types (𝓤niverse)
+//	 T:  &term{false, T}  == {T}                    // set of type T
+//	~t:  &term{true, t}   == {t' | under(t') == t}  // set of types with underlying type t
+type term struct {
+	tilde bool // valid if typ != nil
+	typ   types.Type
+}
+
+func (x *term) String() string {
+	switch {
+	case x == nil:
+		return "∅"
+	case x.typ == nil:
+		return "𝓤"
+	case x.tilde:
+		return "~" + x.typ.String()
+	default:
+		return x.typ.String()
+	}
+}
+
+// equal reports whether x and y represent the same type set.
+func (x *term) equal(y *term) bool {
+	// easy cases
+	switch {
+	case x == nil || y == nil:
+		return x == y
+	case x.typ == nil || y.typ == nil:
+		return x.typ == y.typ
+	}
+	// ∅ ⊂ x, y ⊂ 𝓤
+
+	return x.tilde == y.tilde && types.Identical(x.typ, y.typ)
+}
+
+// union returns the union x ∪ y: zero, one, or two non-nil terms.
+func (x *term) union(y *term) (_, _ *term) {
+	// easy cases
+	switch {
+	case x == nil && y == nil:
+		return nil, nil // ∅ ∪ ∅ == ∅
+	case x == nil:
+		return y, nil // ∅ ∪ y == y
+	case y == nil:
+		return x, nil // x ∪ ∅ == x
+	case x.typ == nil:
+		return x, nil // 𝓤 ∪ y == 𝓤
+	case y.typ == nil:
+		return y, nil // x ∪ 𝓤 == 𝓤
+	}
+	// ∅ ⊂ x, y ⊂ 𝓤
+
+	if x.disjoint(y) {
+		return x, y // x ∪ y == (x, y) if x ∩ y == ∅
+	}
+	// x.typ == y.typ
+
+	// ~t ∪ ~t == ~t
+	// ~t ∪  T == ~t
+	//  T ∪ ~t == ~t
+	//  T ∪  T ==  T
+	if x.tilde || !y.tilde {
+		return x, nil
+	}
+	return y, nil
+}
+
+// intersect returns the intersection x ∩ y.
+func (x *term) intersect(y *term) *term {
+	// easy cases
+	switch {
+	case x == nil || y == nil:
+		return nil // ∅ ∩ y == ∅ and ∩ ∅ == ∅
+	case x.typ == nil:
+		return y // 𝓤 ∩ y == y
+	case y.typ == nil:
+		return x // x ∩ 𝓤 == x
+	}
+	// ∅ ⊂ x, y ⊂ 𝓤
+
+	if x.disjoint(y) {
+		return nil // x ∩ y == ∅ if x ∩ y == ∅
+	}
+	// x.typ == y.typ
+
+	// ~t ∩ ~t == ~t
+	// ~t ∩  T ==  T
+	//  T ∩ ~t ==  T
+	//  T ∩  T ==  T
+	if !x.tilde || y.tilde {
+		return x
+	}
+	return y
+}
+
+// includes reports whether t ∈ x.
+func (x *term) includes(t types.Type) bool {
+	// easy cases
+	switch {
+	case x == nil:
+		return false // t ∈ ∅ == false
+	case x.typ == nil:
+		return true // t ∈ 𝓤 == true
+	}
+	// ∅ ⊂ x ⊂ 𝓤
+
+	u := t
+	if x.tilde {
+		u = under(u)
+	}
+	return types.Identical(x.typ, u)
+}
+
+// subsetOf reports whether x ⊆ y.
+func (x *term) subsetOf(y *term) bool {
+	// easy cases
+	switch {
+	case x == nil:
+		return true // ∅ ⊆ y == true
+	case y == nil:
+		return false // x ⊆ ∅ == false since x != ∅
+	case y.typ == nil:
+		return true // x ⊆ 𝓤 == true
+	case x.typ == nil:
+		return false // 𝓤 ⊆ y == false since y != 𝓤
+	}
+	// ∅ ⊂ x, y ⊂ 𝓤
+
+	if x.disjoint(y) {
+		return false // x ⊆ y == false if x ∩ y == ∅
+	}
+	// x.typ == y.typ
+
+	// ~t ⊆ ~t == true
+	// ~t ⊆ T == false
+	//  T ⊆ ~t == true
+	//  T ⊆  T == true
+	return !x.tilde || y.tilde
+}
+
+// disjoint reports whether x ∩ y == ∅.
+// x.typ and y.typ must not be nil.
+func (x *term) disjoint(y *term) bool {
+	if debug && (x.typ == nil || y.typ == nil) {
+		panic("invalid argument(s)")
+	}
+	ux := x.typ
+	if y.tilde {
+		ux = under(ux)
+	}
+	uy := y.typ
+	if x.tilde {
+		uy = under(uy)
+	}
+	return !types.Identical(ux, uy)
+}
diff --git a/vendor/golang.org/x/tools/internal/typesinternal/element.go b/vendor/golang.org/x/tools/internal/typesinternal/element.go
new file mode 100644
index 0000000000..4957f02164
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/typesinternal/element.go
@@ -0,0 +1,133 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package typesinternal
+
+import (
+	"fmt"
+	"go/types"
+
+	"golang.org/x/tools/go/types/typeutil"
+)
+
+// ForEachElement calls f for type T and each type reachable from its
+// type through reflection. It does this by recursively stripping off
+// type constructors; in addition, for each named type N, the type *N
+// is added to the result as it may have additional methods.
+//
+// The caller must provide an initially empty set used to de-duplicate
+// identical types, potentially across multiple calls to ForEachElement.
+// (Its final value holds all the elements seen, matching the arguments
+// passed to f.)
+//
+// TODO(adonovan): share/harmonize with go/callgraph/rta.
+func ForEachElement(rtypes *typeutil.Map, msets *typeutil.MethodSetCache, T types.Type, f func(types.Type)) {
+	var visit func(T types.Type, skip bool)
+	visit = func(T types.Type, skip bool) {
+		if !skip {
+			if seen, _ := rtypes.Set(T, true).(bool); seen {
+				return // de-dup
+			}
+
+			f(T) // notify caller of new element type
+		}
+
+		// Recursion over signatures of each method.
+		tmset := msets.MethodSet(T)
+		for i := 0; i < tmset.Len(); i++ {
+			sig := tmset.At(i).Type().(*types.Signature)
+			// It is tempting to call visit(sig, false)
+			// but, as noted in golang.org/cl/65450043,
+			// the Signature.Recv field is ignored by
+			// types.Identical and typeutil.Map, which
+			// is confusing at best.
+			//
+			// More importantly, the true signature rtype
+			// reachable from a method using reflection
+			// has no receiver but an extra ordinary parameter.
+			// For the Read method of io.Reader we want:
+			//   func(Reader, []byte) (int, error)
+			// but here sig is:
+			//   func([]byte) (int, error)
+			// with .Recv = Reader (though it is hard to
+			// notice because it doesn't affect Signature.String
+			// or types.Identical).
+			//
+			// TODO(adonovan): construct and visit the correct
+			// non-method signature with an extra parameter
+			// (though since unnamed func types have no methods
+			// there is essentially no actual demand for this).
+			//
+			// TODO(adonovan): document whether or not it is
+			// safe to skip non-exported methods (as RTA does).
+			visit(sig.Params(), true)  // skip the Tuple
+			visit(sig.Results(), true) // skip the Tuple
+		}
+
+		switch T := T.(type) {
+		case *types.Alias:
+			visit(types.Unalias(T), skip) // emulates the pre-Alias behavior
+
+		case *types.Basic:
+			// nop
+
+		case *types.Interface:
+			// nop---handled by recursion over method set.
+
+		case *types.Pointer:
+			visit(T.Elem(), false)
+
+		case *types.Slice:
+			visit(T.Elem(), false)
+
+		case *types.Chan:
+			visit(T.Elem(), false)
+
+		case *types.Map:
+			visit(T.Key(), false)
+			visit(T.Elem(), false)
+
+		case *types.Signature:
+			if T.Recv() != nil {
+				panic(fmt.Sprintf("Signature %s has Recv %s", T, T.Recv()))
+			}
+			visit(T.Params(), true)  // skip the Tuple
+			visit(T.Results(), true) // skip the Tuple
+
+		case *types.Named:
+			// A pointer-to-named type can be derived from a named
+			// type via reflection.  It may have methods too.
+			visit(types.NewPointer(T), false)
+
+			// Consider 'type T struct{S}' where S has methods.
+			// Reflection provides no way to get from T to struct{S},
+			// only to S, so the method set of struct{S} is unwanted,
+			// so set 'skip' flag during recursion.
+			visit(T.Underlying(), true) // skip the unnamed type
+
+		case *types.Array:
+			visit(T.Elem(), false)
+
+		case *types.Struct:
+			for i, n := 0, T.NumFields(); i < n; i++ {
+				// TODO(adonovan): document whether or not
+				// it is safe to skip non-exported fields.
+				visit(T.Field(i).Type(), false)
+			}
+
+		case *types.Tuple:
+			for i, n := 0, T.Len(); i < n; i++ {
+				visit(T.At(i).Type(), false)
+			}
+
+		case *types.TypeParam, *types.Union:
+			// forEachReachable must not be called on parameterized types.
+			panic(T)
+
+		default:
+			panic(T)
+		}
+	}
+	visit(T, false)
+}
diff --git a/vendor/golang.org/x/tools/internal/typesinternal/errorcode.go b/vendor/golang.org/x/tools/internal/typesinternal/errorcode.go
index 131caab284..235a6defc4 100644
--- a/vendor/golang.org/x/tools/internal/typesinternal/errorcode.go
+++ b/vendor/golang.org/x/tools/internal/typesinternal/errorcode.go
@@ -966,7 +966,7 @@ const (
 	//  var _ = string(x)
 	InvalidConversion
 
-	// InvalidUntypedConversion occurs when an there is no valid implicit
+	// InvalidUntypedConversion occurs when there is no valid implicit
 	// conversion from an untyped value satisfying the type constraints of the
 	// context in which it is used.
 	//
diff --git a/vendor/golang.org/x/tools/internal/typesinternal/qualifier.go b/vendor/golang.org/x/tools/internal/typesinternal/qualifier.go
new file mode 100644
index 0000000000..b64f714eb3
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/typesinternal/qualifier.go
@@ -0,0 +1,46 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package typesinternal
+
+import (
+	"go/ast"
+	"go/types"
+	"strconv"
+)
+
+// FileQualifier returns a [types.Qualifier] function that qualifies
+// imported symbols appropriately based on the import environment of a given
+// file.
+// If the same package is imported multiple times, the last appearance is
+// recorded.
+func FileQualifier(f *ast.File, pkg *types.Package) types.Qualifier {
+	// Construct mapping of import paths to their defined names.
+	// It is only necessary to look at renaming imports.
+	imports := make(map[string]string)
+	for _, imp := range f.Imports {
+		if imp.Name != nil && imp.Name.Name != "_" {
+			path, _ := strconv.Unquote(imp.Path.Value)
+			imports[path] = imp.Name.Name
+		}
+	}
+
+	// Define qualifier to replace full package paths with names of the imports.
+	return func(p *types.Package) string {
+		if p == nil || p == pkg {
+			return ""
+		}
+
+		if name, ok := imports[p.Path()]; ok {
+			if name == "." {
+				return ""
+			} else {
+				return name
+			}
+		}
+
+		// If there is no local renaming, fall back to the package name.
+		return p.Name()
+	}
+}
diff --git a/vendor/golang.org/x/tools/internal/typesinternal/recv.go b/vendor/golang.org/x/tools/internal/typesinternal/recv.go
index fea7c8b75e..8352ea7617 100644
--- a/vendor/golang.org/x/tools/internal/typesinternal/recv.go
+++ b/vendor/golang.org/x/tools/internal/typesinternal/recv.go
@@ -6,20 +6,21 @@ package typesinternal
 
 import (
 	"go/types"
-
-	"golang.org/x/tools/internal/aliases"
 )
 
 // ReceiverNamed returns the named type (if any) associated with the
 // type of recv, which may be of the form N or *N, or aliases thereof.
 // It also reports whether a Pointer was present.
+//
+// The named result may be nil if recv is from a method on an
+// anonymous interface or struct types or in ill-typed code.
 func ReceiverNamed(recv *types.Var) (isPtr bool, named *types.Named) {
 	t := recv.Type()
-	if ptr, ok := aliases.Unalias(t).(*types.Pointer); ok {
+	if ptr, ok := types.Unalias(t).(*types.Pointer); ok {
 		isPtr = true
 		t = ptr.Elem()
 	}
-	named, _ = aliases.Unalias(t).(*types.Named)
+	named, _ = types.Unalias(t).(*types.Named)
 	return
 }
 
@@ -36,7 +37,7 @@ func ReceiverNamed(recv *types.Var) (isPtr bool, named *types.Named) {
 // indirection from the type, regardless of named types (analogous to
 // a LOAD instruction).
 func Unpointer(t types.Type) types.Type {
-	if ptr, ok := aliases.Unalias(t).(*types.Pointer); ok {
+	if ptr, ok := types.Unalias(t).(*types.Pointer); ok {
 		return ptr.Elem()
 	}
 	return t
diff --git a/vendor/golang.org/x/tools/internal/typesinternal/types.go b/vendor/golang.org/x/tools/internal/typesinternal/types.go
index 8392328612..3453487963 100644
--- a/vendor/golang.org/x/tools/internal/typesinternal/types.go
+++ b/vendor/golang.org/x/tools/internal/typesinternal/types.go
@@ -11,6 +11,8 @@ import (
 	"go/types"
 	"reflect"
 	"unsafe"
+
+	"golang.org/x/tools/internal/aliases"
 )
 
 func SetUsesCgo(conf *types.Config) bool {
@@ -63,3 +65,63 @@ func NameRelativeTo(pkg *types.Package) types.Qualifier {
 		return other.Name()
 	}
 }
+
+// A NamedOrAlias is a [types.Type] that is named (as
+// defined by the spec) and capable of bearing type parameters: it
+// abstracts aliases ([types.Alias]) and defined types
+// ([types.Named]).
+//
+// Every type declared by an explicit "type" declaration is a
+// NamedOrAlias. (Built-in type symbols may additionally
+// have type [types.Basic], which is not a NamedOrAlias,
+// though the spec regards them as "named".)
+//
+// NamedOrAlias cannot expose the Origin method, because
+// [types.Alias.Origin] and [types.Named.Origin] have different
+// (covariant) result types; use [Origin] instead.
+type NamedOrAlias interface {
+	types.Type
+	Obj() *types.TypeName
+	// TODO(hxjiang): add method TypeArgs() *types.TypeList after stop supporting go1.22.
+}
+
+// TypeParams is a light shim around t.TypeParams().
+// (go/types.Alias).TypeParams requires >= 1.23.
+func TypeParams(t NamedOrAlias) *types.TypeParamList {
+	switch t := t.(type) {
+	case *types.Alias:
+		return aliases.TypeParams(t)
+	case *types.Named:
+		return t.TypeParams()
+	}
+	return nil
+}
+
+// TypeArgs is a light shim around t.TypeArgs().
+// (go/types.Alias).TypeArgs requires >= 1.23.
+func TypeArgs(t NamedOrAlias) *types.TypeList {
+	switch t := t.(type) {
+	case *types.Alias:
+		return aliases.TypeArgs(t)
+	case *types.Named:
+		return t.TypeArgs()
+	}
+	return nil
+}
+
+// Origin returns the generic type of the Named or Alias type t if it
+// is instantiated, otherwise it returns t.
+func Origin(t NamedOrAlias) NamedOrAlias {
+	switch t := t.(type) {
+	case *types.Alias:
+		return aliases.Origin(t)
+	case *types.Named:
+		return t.Origin()
+	}
+	return t
+}
+
+// IsPackageLevel reports whether obj is a package-level symbol.
+func IsPackageLevel(obj types.Object) bool {
+	return obj.Pkg() != nil && obj.Parent() == obj.Pkg().Scope()
+}
diff --git a/vendor/golang.org/x/tools/internal/typesinternal/varkind.go b/vendor/golang.org/x/tools/internal/typesinternal/varkind.go
new file mode 100644
index 0000000000..e5da049511
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/typesinternal/varkind.go
@@ -0,0 +1,40 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package typesinternal
+
+// TODO(adonovan): when CL 645115 lands, define the go1.25 version of
+// this API that actually does something.
+
+import "go/types"
+
+type VarKind uint8
+
+const (
+	_          VarKind = iota // (not meaningful)
+	PackageVar                // a package-level variable
+	LocalVar                  // a local variable
+	RecvVar                   // a method receiver variable
+	ParamVar                  // a function parameter variable
+	ResultVar                 // a function result variable
+	FieldVar                  // a struct field
+)
+
+func (kind VarKind) String() string {
+	return [...]string{
+		0:          "VarKind(0)",
+		PackageVar: "PackageVar",
+		LocalVar:   "LocalVar",
+		RecvVar:    "RecvVar",
+		ParamVar:   "ParamVar",
+		ResultVar:  "ResultVar",
+		FieldVar:   "FieldVar",
+	}[kind]
+}
+
+// GetVarKind returns an invalid VarKind.
+func GetVarKind(v *types.Var) VarKind { return 0 }
+
+// SetVarKind has no effect.
+func SetVarKind(v *types.Var, kind VarKind) {}
diff --git a/vendor/golang.org/x/tools/internal/typesinternal/zerovalue.go b/vendor/golang.org/x/tools/internal/typesinternal/zerovalue.go
new file mode 100644
index 0000000000..d272949c17
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/typesinternal/zerovalue.go
@@ -0,0 +1,392 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package typesinternal
+
+import (
+	"fmt"
+	"go/ast"
+	"go/token"
+	"go/types"
+	"strings"
+)
+
+// ZeroString returns the string representation of the zero value for any type t.
+// The boolean result indicates whether the type is or contains an invalid type
+// or a non-basic (constraint) interface type.
+//
+// Even for invalid input types, ZeroString may return a partially correct
+// string representation. The caller should use the returned isValid boolean
+// to determine the validity of the expression.
+//
+// When assigning to a wider type (such as 'any'), it's the caller's
+// responsibility to handle any necessary type conversions.
+//
+// This string can be used on the right-hand side of an assignment where the
+// left-hand side has that explicit type.
+// References to named types are qualified by an appropriate (optional)
+// qualifier function.
+// Exception: This does not apply to tuples. Their string representation is
+// informational only and cannot be used in an assignment.
+//
+// See [ZeroExpr] for a variant that returns an [ast.Expr].
+func ZeroString(t types.Type, qual types.Qualifier) (_ string, isValid bool) {
+	switch t := t.(type) {
+	case *types.Basic:
+		switch {
+		case t.Info()&types.IsBoolean != 0:
+			return "false", true
+		case t.Info()&types.IsNumeric != 0:
+			return "0", true
+		case t.Info()&types.IsString != 0:
+			return `""`, true
+		case t.Kind() == types.UnsafePointer:
+			fallthrough
+		case t.Kind() == types.UntypedNil:
+			return "nil", true
+		case t.Kind() == types.Invalid:
+			return "invalid", false
+		default:
+			panic(fmt.Sprintf("ZeroString for unexpected type %v", t))
+		}
+
+	case *types.Pointer, *types.Slice, *types.Chan, *types.Map, *types.Signature:
+		return "nil", true
+
+	case *types.Interface:
+		if !t.IsMethodSet() {
+			return "invalid", false
+		}
+		return "nil", true
+
+	case *types.Named:
+		switch under := t.Underlying().(type) {
+		case *types.Struct, *types.Array:
+			return types.TypeString(t, qual) + "{}", true
+		default:
+			return ZeroString(under, qual)
+		}
+
+	case *types.Alias:
+		switch t.Underlying().(type) {
+		case *types.Struct, *types.Array:
+			return types.TypeString(t, qual) + "{}", true
+		default:
+			// A type parameter can have alias but alias type's underlying type
+			// can never be a type parameter.
+			// Use types.Unalias to preserve the info of type parameter instead
+			// of call Underlying() going right through and get the underlying
+			// type of the type parameter which is always an interface.
+			return ZeroString(types.Unalias(t), qual)
+		}
+
+	case *types.Array, *types.Struct:
+		return types.TypeString(t, qual) + "{}", true
+
+	case *types.TypeParam:
+		// Assumes func new is not shadowed.
+		return "*new(" + types.TypeString(t, qual) + ")", true
+
+	case *types.Tuple:
+		// Tuples are not normal values.
+		// We are currently format as "(t[0], ..., t[n])". Could be something else.
+		isValid := true
+		components := make([]string, t.Len())
+		for i := 0; i < t.Len(); i++ {
+			comp, ok := ZeroString(t.At(i).Type(), qual)
+
+			components[i] = comp
+			isValid = isValid && ok
+		}
+		return "(" + strings.Join(components, ", ") + ")", isValid
+
+	case *types.Union:
+		// Variables of these types cannot be created, so it makes
+		// no sense to ask for their zero value.
+		panic(fmt.Sprintf("invalid type for a variable: %v", t))
+
+	default:
+		panic(t) // unreachable.
+	}
+}
+
+// ZeroExpr returns the ast.Expr representation of the zero value for any type t.
+// The boolean result indicates whether the type is or contains an invalid type
+// or a non-basic (constraint) interface type.
+//
+// Even for invalid input types, ZeroExpr may return a partially correct ast.Expr
+// representation. The caller should use the returned isValid boolean to determine
+// the validity of the expression.
+//
+// This function is designed for types suitable for variables and should not be
+// used with Tuple or Union types.References to named types are qualified by an
+// appropriate (optional) qualifier function.
+//
+// See [ZeroString] for a variant that returns a string.
+func ZeroExpr(t types.Type, qual types.Qualifier) (_ ast.Expr, isValid bool) {
+	switch t := t.(type) {
+	case *types.Basic:
+		switch {
+		case t.Info()&types.IsBoolean != 0:
+			return &ast.Ident{Name: "false"}, true
+		case t.Info()&types.IsNumeric != 0:
+			return &ast.BasicLit{Kind: token.INT, Value: "0"}, true
+		case t.Info()&types.IsString != 0:
+			return &ast.BasicLit{Kind: token.STRING, Value: `""`}, true
+		case t.Kind() == types.UnsafePointer:
+			fallthrough
+		case t.Kind() == types.UntypedNil:
+			return ast.NewIdent("nil"), true
+		case t.Kind() == types.Invalid:
+			return &ast.BasicLit{Kind: token.STRING, Value: `"invalid"`}, false
+		default:
+			panic(fmt.Sprintf("ZeroExpr for unexpected type %v", t))
+		}
+
+	case *types.Pointer, *types.Slice, *types.Chan, *types.Map, *types.Signature:
+		return ast.NewIdent("nil"), true
+
+	case *types.Interface:
+		if !t.IsMethodSet() {
+			return &ast.BasicLit{Kind: token.STRING, Value: `"invalid"`}, false
+		}
+		return ast.NewIdent("nil"), true
+
+	case *types.Named:
+		switch under := t.Underlying().(type) {
+		case *types.Struct, *types.Array:
+			return &ast.CompositeLit{
+				Type: TypeExpr(t, qual),
+			}, true
+		default:
+			return ZeroExpr(under, qual)
+		}
+
+	case *types.Alias:
+		switch t.Underlying().(type) {
+		case *types.Struct, *types.Array:
+			return &ast.CompositeLit{
+				Type: TypeExpr(t, qual),
+			}, true
+		default:
+			return ZeroExpr(types.Unalias(t), qual)
+		}
+
+	case *types.Array, *types.Struct:
+		return &ast.CompositeLit{
+			Type: TypeExpr(t, qual),
+		}, true
+
+	case *types.TypeParam:
+		return &ast.StarExpr{ // *new(T)
+			X: &ast.CallExpr{
+				// Assumes func new is not shadowed.
+				Fun: ast.NewIdent("new"),
+				Args: []ast.Expr{
+					ast.NewIdent(t.Obj().Name()),
+				},
+			},
+		}, true
+
+	case *types.Tuple:
+		// Unlike ZeroString, there is no ast.Expr can express tuple by
+		// "(t[0], ..., t[n])".
+		panic(fmt.Sprintf("invalid type for a variable: %v", t))
+
+	case *types.Union:
+		// Variables of these types cannot be created, so it makes
+		// no sense to ask for their zero value.
+		panic(fmt.Sprintf("invalid type for a variable: %v", t))
+
+	default:
+		panic(t) // unreachable.
+	}
+}
+
+// IsZeroExpr uses simple syntactic heuristics to report whether expr
+// is a obvious zero value, such as 0, "", nil, or false.
+// It cannot do better without type information.
+func IsZeroExpr(expr ast.Expr) bool {
+	switch e := expr.(type) {
+	case *ast.BasicLit:
+		return e.Value == "0" || e.Value == `""`
+	case *ast.Ident:
+		return e.Name == "nil" || e.Name == "false"
+	default:
+		return false
+	}
+}
+
+// TypeExpr returns syntax for the specified type. References to named types
+// are qualified by an appropriate (optional) qualifier function.
+// It may panic for types such as Tuple or Union.
+func TypeExpr(t types.Type, qual types.Qualifier) ast.Expr {
+	switch t := t.(type) {
+	case *types.Basic:
+		switch t.Kind() {
+		case types.UnsafePointer:
+			return &ast.SelectorExpr{X: ast.NewIdent(qual(types.NewPackage("unsafe", "unsafe"))), Sel: ast.NewIdent("Pointer")}
+		default:
+			return ast.NewIdent(t.Name())
+		}
+
+	case *types.Pointer:
+		return &ast.UnaryExpr{
+			Op: token.MUL,
+			X:  TypeExpr(t.Elem(), qual),
+		}
+
+	case *types.Array:
+		return &ast.ArrayType{
+			Len: &ast.BasicLit{
+				Kind:  token.INT,
+				Value: fmt.Sprintf("%d", t.Len()),
+			},
+			Elt: TypeExpr(t.Elem(), qual),
+		}
+
+	case *types.Slice:
+		return &ast.ArrayType{
+			Elt: TypeExpr(t.Elem(), qual),
+		}
+
+	case *types.Map:
+		return &ast.MapType{
+			Key:   TypeExpr(t.Key(), qual),
+			Value: TypeExpr(t.Elem(), qual),
+		}
+
+	case *types.Chan:
+		dir := ast.ChanDir(t.Dir())
+		if t.Dir() == types.SendRecv {
+			dir = ast.SEND | ast.RECV
+		}
+		return &ast.ChanType{
+			Dir:   dir,
+			Value: TypeExpr(t.Elem(), qual),
+		}
+
+	case *types.Signature:
+		var params []*ast.Field
+		for i := 0; i < t.Params().Len(); i++ {
+			params = append(params, &ast.Field{
+				Type: TypeExpr(t.Params().At(i).Type(), qual),
+				Names: []*ast.Ident{
+					{
+						Name: t.Params().At(i).Name(),
+					},
+				},
+			})
+		}
+		if t.Variadic() {
+			last := params[len(params)-1]
+			last.Type = &ast.Ellipsis{Elt: last.Type.(*ast.ArrayType).Elt}
+		}
+		var returns []*ast.Field
+		for i := 0; i < t.Results().Len(); i++ {
+			returns = append(returns, &ast.Field{
+				Type: TypeExpr(t.Results().At(i).Type(), qual),
+			})
+		}
+		return &ast.FuncType{
+			Params: &ast.FieldList{
+				List: params,
+			},
+			Results: &ast.FieldList{
+				List: returns,
+			},
+		}
+
+	case *types.TypeParam:
+		pkgName := qual(t.Obj().Pkg())
+		if pkgName == "" || t.Obj().Pkg() == nil {
+			return ast.NewIdent(t.Obj().Name())
+		}
+		return &ast.SelectorExpr{
+			X:   ast.NewIdent(pkgName),
+			Sel: ast.NewIdent(t.Obj().Name()),
+		}
+
+	// types.TypeParam also implements interface NamedOrAlias. To differentiate,
+	// case TypeParam need to be present before case NamedOrAlias.
+	// TODO(hxjiang): remove this comment once TypeArgs() is added to interface
+	// NamedOrAlias.
+	case NamedOrAlias:
+		var expr ast.Expr = ast.NewIdent(t.Obj().Name())
+		if pkgName := qual(t.Obj().Pkg()); pkgName != "." && pkgName != "" {
+			expr = &ast.SelectorExpr{
+				X:   ast.NewIdent(pkgName),
+				Sel: expr.(*ast.Ident),
+			}
+		}
+
+		// TODO(hxjiang): call t.TypeArgs after adding method TypeArgs() to
+		// typesinternal.NamedOrAlias.
+		if hasTypeArgs, ok := t.(interface{ TypeArgs() *types.TypeList }); ok {
+			if typeArgs := hasTypeArgs.TypeArgs(); typeArgs != nil && typeArgs.Len() > 0 {
+				var indices []ast.Expr
+				for i := range typeArgs.Len() {
+					indices = append(indices, TypeExpr(typeArgs.At(i), qual))
+				}
+				expr = &ast.IndexListExpr{
+					X:       expr,
+					Indices: indices,
+				}
+			}
+		}
+
+		return expr
+
+	case *types.Struct:
+		return ast.NewIdent(t.String())
+
+	case *types.Interface:
+		return ast.NewIdent(t.String())
+
+	case *types.Union:
+		if t.Len() == 0 {
+			panic("Union type should have at least one term")
+		}
+		// Same as go/ast, the return expression will put last term in the
+		// Y field at topmost level of BinaryExpr.
+		// For union of type "float32 | float64 | int64", the structure looks
+		// similar to:
+		// {
+		// 	X: {
+		// 		X: float32,
+		// 		Op: |
+		// 		Y: float64,
+		// 	}
+		// 	Op: |,
+		// 	Y: int64,
+		// }
+		var union ast.Expr
+		for i := range t.Len() {
+			term := t.Term(i)
+			termExpr := TypeExpr(term.Type(), qual)
+			if term.Tilde() {
+				termExpr = &ast.UnaryExpr{
+					Op: token.TILDE,
+					X:  termExpr,
+				}
+			}
+			if i == 0 {
+				union = termExpr
+			} else {
+				union = &ast.BinaryExpr{
+					X:  union,
+					Op: token.OR,
+					Y:  termExpr,
+				}
+			}
+		}
+		return union
+
+	case *types.Tuple:
+		panic("invalid input type types.Tuple")
+
+	default:
+		panic("unreachable")
+	}
+}
diff --git a/vendor/golang.org/x/tools/internal/versions/constraint.go b/vendor/golang.org/x/tools/internal/versions/constraint.go
deleted file mode 100644
index 179063d484..0000000000
--- a/vendor/golang.org/x/tools/internal/versions/constraint.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package versions
-
-import "go/build/constraint"
-
-// ConstraintGoVersion is constraint.GoVersion (if built with go1.21+).
-// Otherwise nil.
-//
-// Deprecate once x/tools is after go1.21.
-var ConstraintGoVersion func(x constraint.Expr) string
diff --git a/vendor/golang.org/x/tools/internal/versions/constraint_go121.go b/vendor/golang.org/x/tools/internal/versions/constraint_go121.go
deleted file mode 100644
index 38011407d5..0000000000
--- a/vendor/golang.org/x/tools/internal/versions/constraint_go121.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-// +build go1.21
-
-package versions
-
-import "go/build/constraint"
-
-func init() {
-	ConstraintGoVersion = constraint.GoVersion
-}
diff --git a/vendor/golang.org/x/tools/internal/versions/toolchain.go b/vendor/golang.org/x/tools/internal/versions/toolchain.go
deleted file mode 100644
index 377bf7a53b..0000000000
--- a/vendor/golang.org/x/tools/internal/versions/toolchain.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package versions
-
-// toolchain is maximum version (<1.22) that the go toolchain used
-// to build the current tool is known to support.
-//
-// When a tool is built with >=1.22, the value of toolchain is unused.
-//
-// x/tools does not support building with go <1.18. So we take this
-// as the minimum possible maximum.
-var toolchain string = Go1_18
diff --git a/vendor/golang.org/x/tools/internal/versions/toolchain_go119.go b/vendor/golang.org/x/tools/internal/versions/toolchain_go119.go
deleted file mode 100644
index f65beed9d8..0000000000
--- a/vendor/golang.org/x/tools/internal/versions/toolchain_go119.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.19
-// +build go1.19
-
-package versions
-
-func init() {
-	if Compare(toolchain, Go1_19) < 0 {
-		toolchain = Go1_19
-	}
-}
diff --git a/vendor/golang.org/x/tools/internal/versions/toolchain_go120.go b/vendor/golang.org/x/tools/internal/versions/toolchain_go120.go
deleted file mode 100644
index 1a9efa126c..0000000000
--- a/vendor/golang.org/x/tools/internal/versions/toolchain_go120.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.20
-// +build go1.20
-
-package versions
-
-func init() {
-	if Compare(toolchain, Go1_20) < 0 {
-		toolchain = Go1_20
-	}
-}
diff --git a/vendor/golang.org/x/tools/internal/versions/toolchain_go121.go b/vendor/golang.org/x/tools/internal/versions/toolchain_go121.go
deleted file mode 100644
index b7ef216dfe..0000000000
--- a/vendor/golang.org/x/tools/internal/versions/toolchain_go121.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.21
-// +build go1.21
-
-package versions
-
-func init() {
-	if Compare(toolchain, Go1_21) < 0 {
-		toolchain = Go1_21
-	}
-}
diff --git a/vendor/golang.org/x/tools/internal/versions/types.go b/vendor/golang.org/x/tools/internal/versions/types.go
index 562eef21fa..0fc10ce4eb 100644
--- a/vendor/golang.org/x/tools/internal/versions/types.go
+++ b/vendor/golang.org/x/tools/internal/versions/types.go
@@ -5,15 +5,29 @@
 package versions
 
 import (
+	"go/ast"
 	"go/types"
 )
 
-// GoVersion returns the Go version of the type package.
-// It returns zero if no version can be determined.
-func GoVersion(pkg *types.Package) string {
-	// TODO(taking): x/tools can call GoVersion() [from 1.21] after 1.25.
-	if pkg, ok := any(pkg).(interface{ GoVersion() string }); ok {
-		return pkg.GoVersion()
+// FileVersion returns a file's Go version.
+// The reported version is an unknown Future version if a
+// version cannot be determined.
+func FileVersion(info *types.Info, file *ast.File) string {
+	// In tools built with Go >= 1.22, the Go version of a file
+	// follow a cascades of sources:
+	// 1) types.Info.FileVersion, which follows the cascade:
+	//   1.a) file version (ast.File.GoVersion),
+	//   1.b) the package version (types.Config.GoVersion), or
+	// 2) is some unknown Future version.
+	//
+	// File versions require a valid package version to be provided to types
+	// in Config.GoVersion. Config.GoVersion is either from the package's module
+	// or the toolchain (go run). This value should be provided by go/packages
+	// or unitchecker.Config.GoVersion.
+	if v := info.FileVersions[file]; IsValid(v) {
+		return v
 	}
-	return ""
+	// Note: we could instead return runtime.Version() [if valid].
+	// This would act as a max version on what a tool can support.
+	return Future
 }
diff --git a/vendor/golang.org/x/tools/internal/versions/types_go121.go b/vendor/golang.org/x/tools/internal/versions/types_go121.go
deleted file mode 100644
index b4345d3349..0000000000
--- a/vendor/golang.org/x/tools/internal/versions/types_go121.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2023 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build !go1.22
-// +build !go1.22
-
-package versions
-
-import (
-	"go/ast"
-	"go/types"
-)
-
-// FileVersion returns a language version (<=1.21) derived from runtime.Version()
-// or an unknown future version.
-func FileVersion(info *types.Info, file *ast.File) string {
-	// In x/tools built with Go <= 1.21, we do not have Info.FileVersions
-	// available. We use a go version derived from the toolchain used to
-	// compile the tool by default.
-	// This will be <= go1.21. We take this as the maximum version that
-	// this tool can support.
-	//
-	// There are no features currently in x/tools that need to tell fine grained
-	// differences for versions <1.22.
-	return toolchain
-}
-
-// InitFileVersions is a noop when compiled with this Go version.
-func InitFileVersions(*types.Info) {}
diff --git a/vendor/golang.org/x/tools/internal/versions/types_go122.go b/vendor/golang.org/x/tools/internal/versions/types_go122.go
deleted file mode 100644
index aac5db62c9..0000000000
--- a/vendor/golang.org/x/tools/internal/versions/types_go122.go
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2023 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build go1.22
-// +build go1.22
-
-package versions
-
-import (
-	"go/ast"
-	"go/types"
-)
-
-// FileVersion returns a file's Go version.
-// The reported version is an unknown Future version if a
-// version cannot be determined.
-func FileVersion(info *types.Info, file *ast.File) string {
-	// In tools built with Go >= 1.22, the Go version of a file
-	// follow a cascades of sources:
-	// 1) types.Info.FileVersion, which follows the cascade:
-	//   1.a) file version (ast.File.GoVersion),
-	//   1.b) the package version (types.Config.GoVersion), or
-	// 2) is some unknown Future version.
-	//
-	// File versions require a valid package version to be provided to types
-	// in Config.GoVersion. Config.GoVersion is either from the package's module
-	// or the toolchain (go run). This value should be provided by go/packages
-	// or unitchecker.Config.GoVersion.
-	if v := info.FileVersions[file]; IsValid(v) {
-		return v
-	}
-	// Note: we could instead return runtime.Version() [if valid].
-	// This would act as a max version on what a tool can support.
-	return Future
-}
-
-// InitFileVersions initializes info to record Go versions for Go files.
-func InitFileVersions(info *types.Info) {
-	info.FileVersions = make(map[*ast.File]string)
-}
diff --git a/vendor/google.golang.org/protobuf/encoding/protojson/decode.go b/vendor/google.golang.org/protobuf/encoding/protojson/decode.go
index cffdfda961..737d6876d5 100644
--- a/vendor/google.golang.org/protobuf/encoding/protojson/decode.go
+++ b/vendor/google.golang.org/protobuf/encoding/protojson/decode.go
@@ -192,11 +192,6 @@ func (d decoder) unmarshalMessage(m protoreflect.Message, skipTypeURL bool) erro
 				fd = fieldDescs.ByTextName(name)
 			}
 		}
-		if flags.ProtoLegacyWeak {
-			if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() {
-				fd = nil // reset since the weak reference is not linked in
-			}
-		}
 
 		if fd == nil {
 			// Field is unknown.
diff --git a/vendor/google.golang.org/protobuf/encoding/prototext/decode.go b/vendor/google.golang.org/protobuf/encoding/prototext/decode.go
index d972a3d98e..b53805056a 100644
--- a/vendor/google.golang.org/protobuf/encoding/prototext/decode.go
+++ b/vendor/google.golang.org/protobuf/encoding/prototext/decode.go
@@ -185,11 +185,6 @@ func (d decoder) unmarshalMessage(m protoreflect.Message, checkDelims bool) erro
 		} else if xtErr != nil && xtErr != protoregistry.NotFound {
 			return d.newError(tok.Pos(), "unable to resolve [%s]: %v", tok.RawString(), xtErr)
 		}
-		if flags.ProtoLegacyWeak {
-			if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() {
-				fd = nil // reset since the weak reference is not linked in
-			}
-		}
 
 		// Handle unknown fields.
 		if fd == nil {
diff --git a/vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go b/vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go
index 7e87c76044..669133d04d 100644
--- a/vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go
+++ b/vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go
@@ -26,7 +26,7 @@ var byteType = reflect.TypeOf(byte(0))
 // The type is the underlying field type (e.g., a repeated field may be
 // represented by []T, but the Go type passed in is just T).
 // A list of enum value descriptors must be provided for enum fields.
-// This does not populate the Enum or Message (except for weak message).
+// This does not populate the Enum or Message.
 //
 // This function is a best effort attempt; parsing errors are ignored.
 func Unmarshal(tag string, goType reflect.Type, evs protoreflect.EnumValueDescriptors) protoreflect.FieldDescriptor {
@@ -109,9 +109,6 @@ func Unmarshal(tag string, goType reflect.Type, evs protoreflect.EnumValueDescri
 			}
 		case s == "packed":
 			f.L1.EditionFeatures.IsPacked = true
-		case strings.HasPrefix(s, "weak="):
-			f.L1.IsWeak = true
-			f.L1.Message = filedesc.PlaceholderMessage(protoreflect.FullName(s[len("weak="):]))
 		case strings.HasPrefix(s, "def="):
 			// The default tag is special in that everything afterwards is the
 			// default regardless of the presence of commas.
@@ -183,9 +180,6 @@ func Marshal(fd protoreflect.FieldDescriptor, enumName string) string {
 		// the exact same semantics from the previous generator.
 		tag = append(tag, "json="+jsonName)
 	}
-	if fd.IsWeak() {
-		tag = append(tag, "weak="+string(fd.Message().FullName()))
-	}
 	// The previous implementation does not tag extension fields as proto3,
 	// even when the field is defined in a proto3 file. Match that behavior
 	// for consistency.
diff --git a/vendor/google.golang.org/protobuf/internal/filedesc/desc.go b/vendor/google.golang.org/protobuf/internal/filedesc/desc.go
index 378b826faa..688aabe434 100644
--- a/vendor/google.golang.org/protobuf/internal/filedesc/desc.go
+++ b/vendor/google.golang.org/protobuf/internal/filedesc/desc.go
@@ -19,7 +19,6 @@ import (
 	"google.golang.org/protobuf/internal/pragma"
 	"google.golang.org/protobuf/internal/strs"
 	"google.golang.org/protobuf/reflect/protoreflect"
-	"google.golang.org/protobuf/reflect/protoregistry"
 )
 
 // Edition is an Enum for proto2.Edition
@@ -275,7 +274,6 @@ type (
 		Kind             protoreflect.Kind
 		StringName       stringName
 		IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto
-		IsWeak           bool // promoted from google.protobuf.FieldOptions
 		IsLazy           bool // promoted from google.protobuf.FieldOptions
 		Default          defaultValue
 		ContainingOneof  protoreflect.OneofDescriptor // must be consistent with Message.Oneofs.Fields
@@ -369,7 +367,7 @@ func (fd *Field) IsPacked() bool {
 	return fd.L1.EditionFeatures.IsPacked
 }
 func (fd *Field) IsExtension() bool { return false }
-func (fd *Field) IsWeak() bool      { return fd.L1.IsWeak }
+func (fd *Field) IsWeak() bool      { return false }
 func (fd *Field) IsLazy() bool      { return fd.L1.IsLazy }
 func (fd *Field) IsList() bool      { return fd.Cardinality() == protoreflect.Repeated && !fd.IsMap() }
 func (fd *Field) IsMap() bool       { return fd.Message() != nil && fd.Message().IsMapEntry() }
@@ -396,11 +394,6 @@ func (fd *Field) Enum() protoreflect.EnumDescriptor {
 	return fd.L1.Enum
 }
 func (fd *Field) Message() protoreflect.MessageDescriptor {
-	if fd.L1.IsWeak {
-		if d, _ := protoregistry.GlobalFiles.FindDescriptorByName(fd.L1.Message.FullName()); d != nil {
-			return d.(protoreflect.MessageDescriptor)
-		}
-	}
 	return fd.L1.Message
 }
 func (fd *Field) IsMapEntry() bool {
diff --git a/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go b/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go
index 67a51b327c..d4c94458bd 100644
--- a/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go
+++ b/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go
@@ -32,11 +32,6 @@ func (file *File) resolveMessages() {
 		for j := range md.L2.Fields.List {
 			fd := &md.L2.Fields.List[j]
 
-			// Weak fields are resolved upon actual use.
-			if fd.L1.IsWeak {
-				continue
-			}
-
 			// Resolve message field dependency.
 			switch fd.L1.Kind {
 			case protoreflect.EnumKind:
@@ -150,8 +145,6 @@ func (fd *File) unmarshalFull(b []byte) {
 			switch num {
 			case genid.FileDescriptorProto_PublicDependency_field_number:
 				fd.L2.Imports[v].IsPublic = true
-			case genid.FileDescriptorProto_WeakDependency_field_number:
-				fd.L2.Imports[v].IsWeak = true
 			}
 		case protowire.BytesType:
 			v, m := protowire.ConsumeBytes(b)
@@ -502,8 +495,6 @@ func (fd *Field) unmarshalOptions(b []byte) {
 			switch num {
 			case genid.FieldOptions_Packed_field_number:
 				fd.L1.EditionFeatures.IsPacked = protowire.DecodeBool(v)
-			case genid.FieldOptions_Weak_field_number:
-				fd.L1.IsWeak = protowire.DecodeBool(v)
 			case genid.FieldOptions_Lazy_field_number:
 				fd.L1.IsLazy = protowire.DecodeBool(v)
 			case FieldOptions_EnforceUTF8:
diff --git a/vendor/google.golang.org/protobuf/internal/filetype/build.go b/vendor/google.golang.org/protobuf/internal/filetype/build.go
index ba83fea44c..e1b4130bd2 100644
--- a/vendor/google.golang.org/protobuf/internal/filetype/build.go
+++ b/vendor/google.golang.org/protobuf/internal/filetype/build.go
@@ -63,7 +63,7 @@ type Builder struct {
 	// message declarations in "flattened ordering".
 	//
 	// Dependencies are Go types for enums or messages referenced by
-	// message fields (excluding weak fields), for parent extended messages of
+	// message fields, for parent extended messages of
 	// extension fields, for enums or messages referenced by extension fields,
 	// and for input and output messages referenced by service methods.
 	// Dependencies must come after declarations, but the ordering of
diff --git a/vendor/google.golang.org/protobuf/internal/flags/flags.go b/vendor/google.golang.org/protobuf/internal/flags/flags.go
index 5cb3ee70f9..a06ccabc2f 100644
--- a/vendor/google.golang.org/protobuf/internal/flags/flags.go
+++ b/vendor/google.golang.org/protobuf/internal/flags/flags.go
@@ -6,7 +6,7 @@
 package flags
 
 // ProtoLegacy specifies whether to enable support for legacy functionality
-// such as MessageSets, weak fields, and various other obscure behavior
+// such as MessageSets, and various other obscure behavior
 // that is necessary to maintain backwards compatibility with proto1 or
 // the pre-release variants of proto2 and proto3.
 //
@@ -22,8 +22,3 @@ const ProtoLegacy = protoLegacy
 // extension fields at unmarshal time, but defers creating the message
 // structure until the extension is first accessed.
 const LazyUnmarshalExtensions = ProtoLegacy
-
-// ProtoLegacyWeak specifies whether to enable support for weak fields.
-// This flag was split out of ProtoLegacy in preparation for removing
-// support for weak fields (independent of the other protolegacy features).
-const ProtoLegacyWeak = ProtoLegacy
diff --git a/vendor/google.golang.org/protobuf/internal/genid/goname.go b/vendor/google.golang.org/protobuf/internal/genid/goname.go
index 693d2e9e1f..99bb95bafd 100644
--- a/vendor/google.golang.org/protobuf/internal/genid/goname.go
+++ b/vendor/google.golang.org/protobuf/internal/genid/goname.go
@@ -11,15 +11,10 @@ const (
 	SizeCache_goname  = "sizeCache"
 	SizeCacheA_goname = "XXX_sizecache"
 
-	WeakFields_goname  = "weakFields"
-	WeakFieldsA_goname = "XXX_weak"
-
 	UnknownFields_goname  = "unknownFields"
 	UnknownFieldsA_goname = "XXX_unrecognized"
 
 	ExtensionFields_goname  = "extensionFields"
 	ExtensionFieldsA_goname = "XXX_InternalExtensions"
 	ExtensionFieldsB_goname = "XXX_extensions"
-
-	WeakFieldPrefix_goname = "XXX_weak_"
 )
diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_field.go b/vendor/google.golang.org/protobuf/internal/impl/codec_field.go
index 7c1f66c8c1..d14d7d93cc 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/codec_field.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/codec_field.go
@@ -5,15 +5,12 @@
 package impl
 
 import (
-	"fmt"
 	"reflect"
-	"sync"
 
 	"google.golang.org/protobuf/encoding/protowire"
 	"google.golang.org/protobuf/internal/errors"
 	"google.golang.org/protobuf/proto"
 	"google.golang.org/protobuf/reflect/protoreflect"
-	"google.golang.org/protobuf/reflect/protoregistry"
 	"google.golang.org/protobuf/runtime/protoiface"
 )
 
@@ -121,78 +118,6 @@ func (mi *MessageInfo) initOneofFieldCoders(od protoreflect.OneofDescriptor, si
 	}
 }
 
-func makeWeakMessageFieldCoder(fd protoreflect.FieldDescriptor) pointerCoderFuncs {
-	var once sync.Once
-	var messageType protoreflect.MessageType
-	lazyInit := func() {
-		once.Do(func() {
-			messageName := fd.Message().FullName()
-			messageType, _ = protoregistry.GlobalTypes.FindMessageByName(messageName)
-		})
-	}
-
-	return pointerCoderFuncs{
-		size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
-			m, ok := p.WeakFields().get(f.num)
-			if !ok {
-				return 0
-			}
-			lazyInit()
-			if messageType == nil {
-				panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
-			}
-			return sizeMessage(m, f.tagsize, opts)
-		},
-		marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
-			m, ok := p.WeakFields().get(f.num)
-			if !ok {
-				return b, nil
-			}
-			lazyInit()
-			if messageType == nil {
-				panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
-			}
-			return appendMessage(b, m, f.wiretag, opts)
-		},
-		unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
-			fs := p.WeakFields()
-			m, ok := fs.get(f.num)
-			if !ok {
-				lazyInit()
-				if messageType == nil {
-					return unmarshalOutput{}, errUnknown
-				}
-				m = messageType.New().Interface()
-				fs.set(f.num, m)
-			}
-			return consumeMessage(b, m, wtyp, opts)
-		},
-		isInit: func(p pointer, f *coderFieldInfo) error {
-			m, ok := p.WeakFields().get(f.num)
-			if !ok {
-				return nil
-			}
-			return proto.CheckInitialized(m)
-		},
-		merge: func(dst, src pointer, f *coderFieldInfo, opts mergeOptions) {
-			sm, ok := src.WeakFields().get(f.num)
-			if !ok {
-				return
-			}
-			dm, ok := dst.WeakFields().get(f.num)
-			if !ok {
-				lazyInit()
-				if messageType == nil {
-					panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
-				}
-				dm = messageType.New().Interface()
-				dst.WeakFields().set(f.num, dm)
-			}
-			opts.Merge(dm, sm)
-		},
-	}
-}
-
 func makeMessageFieldCoder(fd protoreflect.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
 	if mi := getMessageInfo(ft); mi != nil {
 		funcs := pointerCoderFuncs{
diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_message.go b/vendor/google.golang.org/protobuf/internal/impl/codec_message.go
index 111d95833d..f78b57b046 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/codec_message.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/codec_message.go
@@ -119,9 +119,6 @@ func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) {
 			}
 		case isOneof:
 			fieldOffset = offsetOf(fs)
-		case fd.IsWeak():
-			fieldOffset = si.weakOffset
-			funcs = makeWeakMessageFieldCoder(fd)
 		default:
 			fieldOffset = offsetOf(fs)
 			childMessage, funcs = fieldCoder(fd, ft)
diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go b/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go
index f81d7d0db9..41c1f74ef8 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go
@@ -46,9 +46,6 @@ func (mi *MessageInfo) makeOpaqueCoderMethods(t reflect.Type, si opaqueStructInf
 		switch {
 		case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
 			fieldOffset = offsetOf(fs)
-		case fd.IsWeak():
-			fieldOffset = si.weakOffset
-			funcs = makeWeakMessageFieldCoder(fd)
 		case fd.Message() != nil && !fd.IsMap():
 			fieldOffset = offsetOf(fs)
 			if fd.IsList() {
diff --git a/vendor/google.golang.org/protobuf/internal/impl/lazy.go b/vendor/google.golang.org/protobuf/internal/impl/lazy.go
index e8fb6c35b4..c7de31e243 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/lazy.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/lazy.go
@@ -131,7 +131,7 @@ func (mi *MessageInfo) skipField(b []byte, f *coderFieldInfo, wtyp protowire.Typ
 	fmi := f.validation.mi
 	if fmi == nil {
 		fd := mi.Desc.Fields().ByNumber(f.num)
-		if fd == nil || !fd.IsWeak() {
+		if fd == nil {
 			return out, ValidationUnknown
 		}
 		messageName := fd.Message().FullName()
diff --git a/vendor/google.golang.org/protobuf/internal/impl/legacy_message.go b/vendor/google.golang.org/protobuf/internal/impl/legacy_message.go
index bf0b6049b4..a51dffbe29 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/legacy_message.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/legacy_message.go
@@ -310,12 +310,9 @@ func aberrantAppendField(md *filedesc.Message, goType reflect.Type, tag, tagKey,
 	fd.L0.Parent = md
 	fd.L0.Index = n
 
-	if fd.L1.IsWeak || fd.L1.EditionFeatures.IsPacked {
+	if fd.L1.EditionFeatures.IsPacked {
 		fd.L1.Options = func() protoreflect.ProtoMessage {
 			opts := descopts.Field.ProtoReflect().New()
-			if fd.L1.IsWeak {
-				opts.Set(opts.Descriptor().Fields().ByName("weak"), protoreflect.ValueOfBool(true))
-			}
 			if fd.L1.EditionFeatures.IsPacked {
 				opts.Set(opts.Descriptor().Fields().ByName("packed"), protoreflect.ValueOfBool(fd.L1.EditionFeatures.IsPacked))
 			}
diff --git a/vendor/google.golang.org/protobuf/internal/impl/message.go b/vendor/google.golang.org/protobuf/internal/impl/message.go
index d1f79b4224..d50423dcb7 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/message.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/message.go
@@ -14,7 +14,6 @@ import (
 
 	"google.golang.org/protobuf/internal/genid"
 	"google.golang.org/protobuf/reflect/protoreflect"
-	"google.golang.org/protobuf/reflect/protoregistry"
 )
 
 // MessageInfo provides protobuf related functionality for a given Go type
@@ -120,7 +119,6 @@ type (
 
 var (
 	sizecacheType       = reflect.TypeOf(SizeCache(0))
-	weakFieldsType      = reflect.TypeOf(WeakFields(nil))
 	unknownFieldsAType  = reflect.TypeOf(unknownFieldsA(nil))
 	unknownFieldsBType  = reflect.TypeOf(unknownFieldsB(nil))
 	extensionFieldsType = reflect.TypeOf(ExtensionFields(nil))
@@ -129,8 +127,6 @@ var (
 type structInfo struct {
 	sizecacheOffset offset
 	sizecacheType   reflect.Type
-	weakOffset      offset
-	weakType        reflect.Type
 	unknownOffset   offset
 	unknownType     reflect.Type
 	extensionOffset offset
@@ -148,7 +144,6 @@ type structInfo struct {
 func (mi *MessageInfo) makeStructInfo(t reflect.Type) structInfo {
 	si := structInfo{
 		sizecacheOffset: invalidOffset,
-		weakOffset:      invalidOffset,
 		unknownOffset:   invalidOffset,
 		extensionOffset: invalidOffset,
 		lazyOffset:      invalidOffset,
@@ -168,11 +163,6 @@ fieldLoop:
 				si.sizecacheOffset = offsetOf(f)
 				si.sizecacheType = f.Type
 			}
-		case genid.WeakFields_goname, genid.WeakFieldsA_goname:
-			if f.Type == weakFieldsType {
-				si.weakOffset = offsetOf(f)
-				si.weakType = f.Type
-			}
 		case genid.UnknownFields_goname, genid.UnknownFieldsA_goname:
 			if f.Type == unknownFieldsAType || f.Type == unknownFieldsBType {
 				si.unknownOffset = offsetOf(f)
@@ -256,9 +246,6 @@ func (mi *MessageInfo) Message(i int) protoreflect.MessageType {
 	mi.init()
 	fd := mi.Desc.Fields().Get(i)
 	switch {
-	case fd.IsWeak():
-		mt, _ := protoregistry.GlobalTypes.FindMessageByName(fd.Message().FullName())
-		return mt
 	case fd.IsMap():
 		return mapEntryType{fd.Message(), mi.fieldTypes[fd.Number()]}
 	default:
diff --git a/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go b/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go
index d8dcd78863..dd55e8e009 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go
@@ -56,9 +56,6 @@ func opaqueInitHook(mi *MessageInfo) bool {
 		usePresence, _ := usePresenceForField(si, fd)
 
 		switch {
-		case fd.IsWeak():
-			// Weak fields are no different for opaque.
-			fi = fieldInfoForWeakMessage(fd, si.weakOffset)
 		case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
 			// Oneofs are no different for opaque.
 			fi = fieldInfoForOneof(fd, si.oneofsByName[fd.ContainingOneof().Name()], mi.Exporter, si.oneofWrappersByNumber[fd.Number()])
@@ -620,8 +617,6 @@ func usePresenceForField(si opaqueStructInfo, fd protoreflect.FieldDescriptor) (
 	switch {
 	case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
 		return false, false
-	case fd.IsWeak():
-		return false, false
 	case fd.IsMap():
 		return false, false
 	case fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind:
diff --git a/vendor/google.golang.org/protobuf/internal/impl/message_reflect.go b/vendor/google.golang.org/protobuf/internal/impl/message_reflect.go
index 31c19b54f8..0d20132fa2 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/message_reflect.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/message_reflect.go
@@ -72,8 +72,6 @@ func (mi *MessageInfo) makeKnownFieldsFunc(si structInfo) {
 			fi = fieldInfoForMap(fd, fs, mi.Exporter)
 		case fd.IsList():
 			fi = fieldInfoForList(fd, fs, mi.Exporter)
-		case fd.IsWeak():
-			fi = fieldInfoForWeakMessage(fd, si.weakOffset)
 		case fd.Message() != nil:
 			fi = fieldInfoForMessage(fd, fs, mi.Exporter)
 		default:
@@ -219,9 +217,6 @@ func (mi *MessageInfo) makeFieldTypes(si structInfo) {
 			}
 		case fd.Message() != nil:
 			ft = fs.Type
-			if fd.IsWeak() {
-				ft = nil
-			}
 			isMessage = true
 		}
 		if isMessage && ft != nil && ft.Kind() != reflect.Ptr {
diff --git a/vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go b/vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go
index 3cd1fbc21f..68d4ae32ec 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go
@@ -8,11 +8,8 @@ import (
 	"fmt"
 	"math"
 	"reflect"
-	"sync"
 
-	"google.golang.org/protobuf/internal/flags"
 	"google.golang.org/protobuf/reflect/protoreflect"
-	"google.golang.org/protobuf/reflect/protoregistry"
 )
 
 type fieldInfo struct {
@@ -332,79 +329,6 @@ func fieldInfoForScalar(fd protoreflect.FieldDescriptor, fs reflect.StructField,
 	}
 }
 
-func fieldInfoForWeakMessage(fd protoreflect.FieldDescriptor, weakOffset offset) fieldInfo {
-	if !flags.ProtoLegacyWeak {
-		panic("no support for proto1 weak fields")
-	}
-
-	var once sync.Once
-	var messageType protoreflect.MessageType
-	lazyInit := func() {
-		once.Do(func() {
-			messageName := fd.Message().FullName()
-			messageType, _ = protoregistry.GlobalTypes.FindMessageByName(messageName)
-			if messageType == nil {
-				panic(fmt.Sprintf("weak message %v for field %v is not linked in", messageName, fd.FullName()))
-			}
-		})
-	}
-
-	num := fd.Number()
-	return fieldInfo{
-		fieldDesc: fd,
-		has: func(p pointer) bool {
-			if p.IsNil() {
-				return false
-			}
-			_, ok := p.Apply(weakOffset).WeakFields().get(num)
-			return ok
-		},
-		clear: func(p pointer) {
-			p.Apply(weakOffset).WeakFields().clear(num)
-		},
-		get: func(p pointer) protoreflect.Value {
-			lazyInit()
-			if p.IsNil() {
-				return protoreflect.ValueOfMessage(messageType.Zero())
-			}
-			m, ok := p.Apply(weakOffset).WeakFields().get(num)
-			if !ok {
-				return protoreflect.ValueOfMessage(messageType.Zero())
-			}
-			return protoreflect.ValueOfMessage(m.ProtoReflect())
-		},
-		set: func(p pointer, v protoreflect.Value) {
-			lazyInit()
-			m := v.Message()
-			if m.Descriptor() != messageType.Descriptor() {
-				if got, want := m.Descriptor().FullName(), messageType.Descriptor().FullName(); got != want {
-					panic(fmt.Sprintf("field %v has mismatching message descriptor: got %v, want %v", fd.FullName(), got, want))
-				}
-				panic(fmt.Sprintf("field %v has mismatching message descriptor: %v", fd.FullName(), m.Descriptor().FullName()))
-			}
-			p.Apply(weakOffset).WeakFields().set(num, m.Interface())
-		},
-		mutable: func(p pointer) protoreflect.Value {
-			lazyInit()
-			fs := p.Apply(weakOffset).WeakFields()
-			m, ok := fs.get(num)
-			if !ok {
-				m = messageType.New().Interface()
-				fs.set(num, m)
-			}
-			return protoreflect.ValueOfMessage(m.ProtoReflect())
-		},
-		newMessage: func() protoreflect.Message {
-			lazyInit()
-			return messageType.New()
-		},
-		newField: func() protoreflect.Value {
-			lazyInit()
-			return protoreflect.ValueOfMessage(messageType.New())
-		},
-	}
-}
-
 func fieldInfoForMessage(fd protoreflect.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo {
 	ft := fs.Type
 	conv := NewConverter(ft, fd)
diff --git a/vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go b/vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go
index 6bed45e35c..62f8bf663e 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go
@@ -111,7 +111,6 @@ func (p pointer) StringSlice() *[]string                { return (*[]string)(p.p
 func (p pointer) Bytes() *[]byte                        { return (*[]byte)(p.p) }
 func (p pointer) BytesPtr() **[]byte                    { return (**[]byte)(p.p) }
 func (p pointer) BytesSlice() *[][]byte                 { return (*[][]byte)(p.p) }
-func (p pointer) WeakFields() *weakFields               { return (*weakFields)(p.p) }
 func (p pointer) Extensions() *map[int32]ExtensionField { return (*map[int32]ExtensionField)(p.p) }
 func (p pointer) LazyInfoPtr() **protolazy.XXX_lazyUnmarshalInfo {
 	return (**protolazy.XXX_lazyUnmarshalInfo)(p.p)
diff --git a/vendor/google.golang.org/protobuf/internal/impl/validate.go b/vendor/google.golang.org/protobuf/internal/impl/validate.go
index b534a3d6db..7b2995dde5 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/validate.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/validate.go
@@ -211,9 +211,7 @@ func newValidationInfo(fd protoreflect.FieldDescriptor, ft reflect.Type) validat
 		switch fd.Kind() {
 		case protoreflect.MessageKind:
 			vi.typ = validationTypeMessage
-			if !fd.IsWeak() {
-				vi.mi = getMessageInfo(ft)
-			}
+			vi.mi = getMessageInfo(ft)
 		case protoreflect.GroupKind:
 			vi.typ = validationTypeGroup
 			vi.mi = getMessageInfo(ft)
@@ -320,26 +318,6 @@ State:
 				}
 				if f != nil {
 					vi = f.validation
-					if vi.typ == validationTypeMessage && vi.mi == nil {
-						// Probable weak field.
-						//
-						// TODO: Consider storing the results of this lookup somewhere
-						// rather than recomputing it on every validation.
-						fd := st.mi.Desc.Fields().ByNumber(num)
-						if fd == nil || !fd.IsWeak() {
-							break
-						}
-						messageName := fd.Message().FullName()
-						messageType, err := protoregistry.GlobalTypes.FindMessageByName(messageName)
-						switch err {
-						case nil:
-							vi.mi, _ = messageType.(*MessageInfo)
-						case protoregistry.NotFound:
-							vi.typ = validationTypeBytes
-						default:
-							return out, ValidationUnknown
-						}
-					}
 					break
 				}
 				// Possible extension field.
diff --git a/vendor/google.golang.org/protobuf/internal/impl/weak.go b/vendor/google.golang.org/protobuf/internal/impl/weak.go
deleted file mode 100644
index eb79a7ba94..0000000000
--- a/vendor/google.golang.org/protobuf/internal/impl/weak.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2019 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package impl
-
-import (
-	"fmt"
-
-	"google.golang.org/protobuf/reflect/protoreflect"
-	"google.golang.org/protobuf/reflect/protoregistry"
-)
-
-// weakFields adds methods to the exported WeakFields type for internal use.
-//
-// The exported type is an alias to an unnamed type, so methods can't be
-// defined directly on it.
-type weakFields WeakFields
-
-func (w weakFields) get(num protoreflect.FieldNumber) (protoreflect.ProtoMessage, bool) {
-	m, ok := w[int32(num)]
-	return m, ok
-}
-
-func (w *weakFields) set(num protoreflect.FieldNumber, m protoreflect.ProtoMessage) {
-	if *w == nil {
-		*w = make(weakFields)
-	}
-	(*w)[int32(num)] = m
-}
-
-func (w *weakFields) clear(num protoreflect.FieldNumber) {
-	delete(*w, int32(num))
-}
-
-func (Export) HasWeak(w WeakFields, num protoreflect.FieldNumber) bool {
-	_, ok := w[int32(num)]
-	return ok
-}
-
-func (Export) ClearWeak(w *WeakFields, num protoreflect.FieldNumber) {
-	delete(*w, int32(num))
-}
-
-func (Export) GetWeak(w WeakFields, num protoreflect.FieldNumber, name protoreflect.FullName) protoreflect.ProtoMessage {
-	if m, ok := w[int32(num)]; ok {
-		return m
-	}
-	mt, _ := protoregistry.GlobalTypes.FindMessageByName(name)
-	if mt == nil {
-		panic(fmt.Sprintf("message %v for weak field is not linked in", name))
-	}
-	return mt.Zero().Interface()
-}
-
-func (Export) SetWeak(w *WeakFields, num protoreflect.FieldNumber, name protoreflect.FullName, m protoreflect.ProtoMessage) {
-	if m != nil {
-		mt, _ := protoregistry.GlobalTypes.FindMessageByName(name)
-		if mt == nil {
-			panic(fmt.Sprintf("message %v for weak field is not linked in", name))
-		}
-		if mt != m.ProtoReflect().Type() {
-			panic(fmt.Sprintf("invalid message type for weak field: got %T, want %T", m, mt.Zero().Interface()))
-		}
-	}
-	if m == nil || !m.ProtoReflect().IsValid() {
-		delete(*w, int32(num))
-		return
-	}
-	if *w == nil {
-		*w = make(weakFields)
-	}
-	(*w)[int32(num)] = m
-}
diff --git a/vendor/google.golang.org/protobuf/internal/version/version.go b/vendor/google.golang.org/protobuf/internal/version/version.go
index 4a39af0c63..01efc33030 100644
--- a/vendor/google.golang.org/protobuf/internal/version/version.go
+++ b/vendor/google.golang.org/protobuf/internal/version/version.go
@@ -52,7 +52,7 @@ import (
 const (
 	Major      = 1
 	Minor      = 36
-	Patch      = 4
+	Patch      = 5
 	PreRelease = ""
 )
 
diff --git a/vendor/google.golang.org/protobuf/proto/decode.go b/vendor/google.golang.org/protobuf/proto/decode.go
index e28d7acb37..4cbf1aeaf7 100644
--- a/vendor/google.golang.org/protobuf/proto/decode.go
+++ b/vendor/google.golang.org/protobuf/proto/decode.go
@@ -8,7 +8,6 @@ import (
 	"google.golang.org/protobuf/encoding/protowire"
 	"google.golang.org/protobuf/internal/encoding/messageset"
 	"google.golang.org/protobuf/internal/errors"
-	"google.golang.org/protobuf/internal/flags"
 	"google.golang.org/protobuf/internal/genid"
 	"google.golang.org/protobuf/internal/pragma"
 	"google.golang.org/protobuf/reflect/protoreflect"
@@ -172,10 +171,6 @@ func (o UnmarshalOptions) unmarshalMessageSlow(b []byte, m protoreflect.Message)
 		var err error
 		if fd == nil {
 			err = errUnknown
-		} else if flags.ProtoLegacyWeak {
-			if fd.IsWeak() && fd.Message().IsPlaceholder() {
-				err = errUnknown // weak referent is not linked in
-			}
 		}
 
 		// Parse the field value.
diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go b/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go
index 69a0505091..823dbf3ba6 100644
--- a/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go
+++ b/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go
@@ -132,17 +132,11 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot
 		}
 		f.L2.Imports[i].IsPublic = true
 	}
-	for _, i := range fd.GetWeakDependency() {
-		if !(0 <= i && int(i) < len(f.L2.Imports)) || f.L2.Imports[i].IsWeak {
-			return nil, errors.New("invalid or duplicate weak import index: %d", i)
-		}
-		f.L2.Imports[i].IsWeak = true
-	}
 	imps := importSet{f.Path(): true}
 	for i, path := range fd.GetDependency() {
 		imp := &f.L2.Imports[i]
 		f, err := r.FindFileByPath(path)
-		if err == protoregistry.NotFound && (o.AllowUnresolvable || imp.IsWeak) {
+		if err == protoregistry.NotFound && o.AllowUnresolvable {
 			f = filedesc.PlaceholderFile(path)
 		} else if err != nil {
 			return nil, errors.New("could not resolve import %q: %v", path, err)
diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go
index ebcb4a8ab1..9da34998b1 100644
--- a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go
+++ b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go
@@ -149,7 +149,6 @@ func (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDesc
 		if opts := fd.GetOptions(); opts != nil {
 			opts = proto.Clone(opts).(*descriptorpb.FieldOptions)
 			f.L1.Options = func() protoreflect.ProtoMessage { return opts }
-			f.L1.IsWeak = opts.GetWeak()
 			f.L1.IsLazy = opts.GetLazy()
 			if opts.Packed != nil {
 				f.L1.EditionFeatures.IsPacked = opts.GetPacked()
diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go
index f3cebab29c..ff692436e9 100644
--- a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go
+++ b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go
@@ -43,7 +43,7 @@ func (r *resolver) resolveMessageDependencies(ms []filedesc.Message, mds []*desc
 				o.L1.Fields.List = append(o.L1.Fields.List, f)
 			}
 
-			if f.L1.Kind, f.L1.Enum, f.L1.Message, err = r.findTarget(f.Kind(), f.Parent().FullName(), partialName(fd.GetTypeName()), f.IsWeak()); err != nil {
+			if f.L1.Kind, f.L1.Enum, f.L1.Message, err = r.findTarget(f.Kind(), f.Parent().FullName(), partialName(fd.GetTypeName())); err != nil {
 				return errors.New("message field %q cannot resolve type: %v", f.FullName(), err)
 			}
 			if f.L1.Kind == protoreflect.GroupKind && (f.IsMap() || f.IsMapEntry()) {
@@ -73,10 +73,10 @@ func (r *resolver) resolveMessageDependencies(ms []filedesc.Message, mds []*desc
 func (r *resolver) resolveExtensionDependencies(xs []filedesc.Extension, xds []*descriptorpb.FieldDescriptorProto) (err error) {
 	for i, xd := range xds {
 		x := &xs[i]
-		if x.L1.Extendee, err = r.findMessageDescriptor(x.Parent().FullName(), partialName(xd.GetExtendee()), false); err != nil {
+		if x.L1.Extendee, err = r.findMessageDescriptor(x.Parent().FullName(), partialName(xd.GetExtendee())); err != nil {
 			return errors.New("extension field %q cannot resolve extendee: %v", x.FullName(), err)
 		}
-		if x.L1.Kind, x.L2.Enum, x.L2.Message, err = r.findTarget(x.Kind(), x.Parent().FullName(), partialName(xd.GetTypeName()), false); err != nil {
+		if x.L1.Kind, x.L2.Enum, x.L2.Message, err = r.findTarget(x.Kind(), x.Parent().FullName(), partialName(xd.GetTypeName())); err != nil {
 			return errors.New("extension field %q cannot resolve type: %v", x.FullName(), err)
 		}
 		if xd.DefaultValue != nil {
@@ -95,11 +95,11 @@ func (r *resolver) resolveServiceDependencies(ss []filedesc.Service, sds []*desc
 		s := &ss[i]
 		for j, md := range sd.GetMethod() {
 			m := &s.L2.Methods.List[j]
-			m.L1.Input, err = r.findMessageDescriptor(m.Parent().FullName(), partialName(md.GetInputType()), false)
+			m.L1.Input, err = r.findMessageDescriptor(m.Parent().FullName(), partialName(md.GetInputType()))
 			if err != nil {
 				return errors.New("service method %q cannot resolve input: %v", m.FullName(), err)
 			}
-			m.L1.Output, err = r.findMessageDescriptor(s.FullName(), partialName(md.GetOutputType()), false)
+			m.L1.Output, err = r.findMessageDescriptor(s.FullName(), partialName(md.GetOutputType()))
 			if err != nil {
 				return errors.New("service method %q cannot resolve output: %v", m.FullName(), err)
 			}
@@ -111,16 +111,16 @@ func (r *resolver) resolveServiceDependencies(ss []filedesc.Service, sds []*desc
 // findTarget finds an enum or message descriptor if k is an enum, message,
 // group, or unknown. If unknown, and the name could be resolved, the kind
 // returned kind is set based on the type of the resolved descriptor.
-func (r *resolver) findTarget(k protoreflect.Kind, scope protoreflect.FullName, ref partialName, isWeak bool) (protoreflect.Kind, protoreflect.EnumDescriptor, protoreflect.MessageDescriptor, error) {
+func (r *resolver) findTarget(k protoreflect.Kind, scope protoreflect.FullName, ref partialName) (protoreflect.Kind, protoreflect.EnumDescriptor, protoreflect.MessageDescriptor, error) {
 	switch k {
 	case protoreflect.EnumKind:
-		ed, err := r.findEnumDescriptor(scope, ref, isWeak)
+		ed, err := r.findEnumDescriptor(scope, ref)
 		if err != nil {
 			return 0, nil, nil, err
 		}
 		return k, ed, nil, nil
 	case protoreflect.MessageKind, protoreflect.GroupKind:
-		md, err := r.findMessageDescriptor(scope, ref, isWeak)
+		md, err := r.findMessageDescriptor(scope, ref)
 		if err != nil {
 			return 0, nil, nil, err
 		}
@@ -129,7 +129,7 @@ func (r *resolver) findTarget(k protoreflect.Kind, scope protoreflect.FullName,
 		// Handle unspecified kinds (possible with parsers that operate
 		// on a per-file basis without knowledge of dependencies).
 		d, err := r.findDescriptor(scope, ref)
-		if err == protoregistry.NotFound && (r.allowUnresolvable || isWeak) {
+		if err == protoregistry.NotFound && r.allowUnresolvable {
 			return k, filedesc.PlaceholderEnum(ref.FullName()), filedesc.PlaceholderMessage(ref.FullName()), nil
 		} else if err == protoregistry.NotFound {
 			return 0, nil, nil, errors.New("%q not found", ref.FullName())
@@ -206,9 +206,9 @@ func (r *resolver) findDescriptor(scope protoreflect.FullName, ref partialName)
 	}
 }
 
-func (r *resolver) findEnumDescriptor(scope protoreflect.FullName, ref partialName, isWeak bool) (protoreflect.EnumDescriptor, error) {
+func (r *resolver) findEnumDescriptor(scope protoreflect.FullName, ref partialName) (protoreflect.EnumDescriptor, error) {
 	d, err := r.findDescriptor(scope, ref)
-	if err == protoregistry.NotFound && (r.allowUnresolvable || isWeak) {
+	if err == protoregistry.NotFound && r.allowUnresolvable {
 		return filedesc.PlaceholderEnum(ref.FullName()), nil
 	} else if err == protoregistry.NotFound {
 		return nil, errors.New("%q not found", ref.FullName())
@@ -222,9 +222,9 @@ func (r *resolver) findEnumDescriptor(scope protoreflect.FullName, ref partialNa
 	return ed, nil
 }
 
-func (r *resolver) findMessageDescriptor(scope protoreflect.FullName, ref partialName, isWeak bool) (protoreflect.MessageDescriptor, error) {
+func (r *resolver) findMessageDescriptor(scope protoreflect.FullName, ref partialName) (protoreflect.MessageDescriptor, error) {
 	d, err := r.findDescriptor(scope, ref)
-	if err == protoregistry.NotFound && (r.allowUnresolvable || isWeak) {
+	if err == protoregistry.NotFound && r.allowUnresolvable {
 		return filedesc.PlaceholderMessage(ref.FullName()), nil
 	} else if err == protoregistry.NotFound {
 		return nil, errors.New("%q not found", ref.FullName())
diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go
index 5eaf652176..c343d9227b 100644
--- a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go
+++ b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go
@@ -149,12 +149,6 @@ func validateMessageDeclarations(file *filedesc.File, ms []filedesc.Message, mds
 					return errors.New("message field %q under proto3 optional semantics must be within a single element oneof", f.FullName())
 				}
 			}
-			if f.IsWeak() && !flags.ProtoLegacyWeak {
-				return errors.New("message field %q is a weak field, which is a legacy proto1 feature that is no longer supported", f.FullName())
-			}
-			if f.IsWeak() && (!f.HasPresence() || !isOptionalMessage(f) || f.ContainingOneof() != nil) {
-				return errors.New("message field %q may only be weak for an optional message", f.FullName())
-			}
 			if f.IsPacked() && !isPackable(f) {
 				return errors.New("message field %q is not packable", f.FullName())
 			}
@@ -199,9 +193,6 @@ func validateMessageDeclarations(file *filedesc.File, ms []filedesc.Message, mds
 				if f.Cardinality() != protoreflect.Optional {
 					return errors.New("message field %q belongs in a oneof and must be optional", f.FullName())
 				}
-				if f.IsWeak() {
-					return errors.New("message field %q belongs in a oneof and must not be a weak reference", f.FullName())
-				}
 			}
 		}
 
@@ -254,9 +245,6 @@ func validateExtensionDeclarations(f *filedesc.File, xs []filedesc.Extension, xd
 				return errors.New("extension field %q has an invalid number: %d", x.FullName(), x.Number())
 			}
 		}
-		if xd.GetOptions().GetWeak() {
-			return errors.New("extension field %q cannot be a weak reference", x.FullName())
-		}
 		if x.IsPacked() && !isPackable(x) {
 			return errors.New("extension field %q is not packable", x.FullName())
 		}
diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go b/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go
index a5de8d4001..9b880aa8c9 100644
--- a/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go
+++ b/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go
@@ -32,9 +32,6 @@ func ToFileDescriptorProto(file protoreflect.FileDescriptor) *descriptorpb.FileD
 		if imp.IsPublic {
 			p.PublicDependency = append(p.PublicDependency, int32(i))
 		}
-		if imp.IsWeak {
-			p.WeakDependency = append(p.WeakDependency, int32(i))
-		}
 	}
 	for i, locs := 0, file.SourceLocations(); i < locs.Len(); i++ {
 		loc := locs.Get(i)
diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/type.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/type.go
index cd8fadbaf8..cd7fbc87a4 100644
--- a/vendor/google.golang.org/protobuf/reflect/protoreflect/type.go
+++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/type.go
@@ -68,7 +68,7 @@ type Descriptor interface {
 	// dependency is not resolved, in which case only name information is known.
 	//
 	// Placeholder types may only be returned by the following accessors
-	// as a result of unresolved dependencies or weak imports:
+	// as a result of unresolved dependencies:
 	//
 	//	╔═══════════════════════════════════╤═════════════════════╗
 	//	║ Accessor                          │ Descriptor          ║
@@ -168,11 +168,7 @@ type FileImport struct {
 	// The current file and the imported file must be within proto package.
 	IsPublic bool
 
-	// IsWeak reports whether this is a weak import, which does not impose
-	// a direct dependency on the target file.
-	//
-	// Weak imports are a legacy proto1 feature. Equivalent behavior is
-	// achieved using proto2 extension fields or proto3 Any messages.
+	// Deprecated: support for weak fields has been removed.
 	IsWeak bool
 }
 
@@ -325,9 +321,7 @@ type FieldDescriptor interface {
 	// specified in the source .proto file.
 	HasOptionalKeyword() bool
 
-	// IsWeak reports whether this is a weak field, which does not impose a
-	// direct dependency on the target type.
-	// If true, then Message returns a placeholder type.
+	// Deprecated: support for weak fields has been removed.
 	IsWeak() bool
 
 	// IsPacked reports whether repeated primitive numeric kinds should be
diff --git a/vendor/modules.txt b/vendor/modules.txt
index f7aa2d25ee..cf60aba055 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -212,8 +212,8 @@ github.com/felixge/httpsnoop
 # github.com/fsnotify/fsnotify v1.7.0
 ## explicit; go 1.17
 github.com/fsnotify/fsnotify
-# github.com/go-chi/chi/v5 v5.1.0
-## explicit; go 1.14
+# github.com/go-chi/chi/v5 v5.2.1
+## explicit; go 1.20
 github.com/go-chi/chi/v5
 # github.com/go-co-op/gocron v1.37.0
 ## explicit; go 1.16
@@ -257,6 +257,9 @@ github.com/go-testfixtures/testfixtures/v3
 ## explicit; go 1.15
 github.com/gogo/protobuf/proto
 github.com/gogo/protobuf/sortkeys
+# github.com/gohugoio/hashstructure v0.5.0
+## explicit; go 1.18
+github.com/gohugoio/hashstructure
 # github.com/golang-jwt/jwt v3.2.2+incompatible
 ## explicit
 github.com/golang-jwt/jwt
@@ -882,8 +885,8 @@ go.uber.org/zap/internal/stacktrace
 go.uber.org/zap/internal/ztest
 go.uber.org/zap/zapcore
 go.uber.org/zap/zaptest
-# goa.design/goa/v3 v3.19.1
-## explicit; go 1.22.0
+# goa.design/goa/v3 v3.20.0
+## explicit; go 1.23.0
 goa.design/goa/v3/codegen
 goa.design/goa/v3/codegen/cli
 goa.design/goa/v3/codegen/example
@@ -902,13 +905,13 @@ goa.design/goa/v3/http/middleware
 goa.design/goa/v3/middleware
 goa.design/goa/v3/pkg
 goa.design/goa/v3/security
-# goa.design/plugins/v3 v3.19.1
-## explicit; go 1.22.0
+# goa.design/plugins/v3 v3.20.0
+## explicit; go 1.23.0
 goa.design/plugins/v3/cors
 goa.design/plugins/v3/cors/dsl
 goa.design/plugins/v3/cors/expr
 goa.design/plugins/v3/zaplogger
-# golang.org/x/crypto v0.32.0
+# golang.org/x/crypto v0.33.0
 ## explicit; go 1.20
 golang.org/x/crypto/chacha20
 golang.org/x/crypto/chacha20poly1305
@@ -931,18 +934,19 @@ golang.org/x/exp/slices
 golang.org/x/exp/slog
 golang.org/x/exp/slog/internal
 golang.org/x/exp/slog/internal/buffer
-# golang.org/x/mod v0.21.0
+# golang.org/x/mod v0.23.0
 ## explicit; go 1.22.0
 golang.org/x/mod/internal/lazyregexp
 golang.org/x/mod/module
 golang.org/x/mod/semver
-# golang.org/x/net v0.34.0
+# golang.org/x/net v0.35.0
 ## explicit; go 1.18
 golang.org/x/net/http/httpguts
 golang.org/x/net/http2
 golang.org/x/net/http2/h2c
 golang.org/x/net/http2/hpack
 golang.org/x/net/idna
+golang.org/x/net/internal/httpcommon
 golang.org/x/net/internal/timeseries
 golang.org/x/net/trace
 # golang.org/x/oauth2 v0.25.0
@@ -995,12 +999,13 @@ golang.org/x/text/width
 # golang.org/x/time v0.8.0
 ## explicit; go 1.18
 golang.org/x/time/rate
-# golang.org/x/tools v0.25.0
+# golang.org/x/tools v0.30.0
 ## explicit; go 1.22.0
 golang.org/x/tools/go/ast/astutil
 golang.org/x/tools/go/gcexportdata
 golang.org/x/tools/go/packages
 golang.org/x/tools/go/types/objectpath
+golang.org/x/tools/go/types/typeutil
 golang.org/x/tools/imports
 golang.org/x/tools/internal/aliases
 golang.org/x/tools/internal/event
@@ -1011,10 +1016,11 @@ golang.org/x/tools/internal/gcimporter
 golang.org/x/tools/internal/gocommand
 golang.org/x/tools/internal/gopathwalk
 golang.org/x/tools/internal/imports
+golang.org/x/tools/internal/modindex
 golang.org/x/tools/internal/packagesinternal
 golang.org/x/tools/internal/pkgbits
 golang.org/x/tools/internal/stdlib
-golang.org/x/tools/internal/tokeninternal
+golang.org/x/tools/internal/typeparams
 golang.org/x/tools/internal/typesinternal
 golang.org/x/tools/internal/versions
 # gomodules.xyz/jsonpatch/v2 v2.4.0
@@ -1049,8 +1055,8 @@ google.golang.org/genproto/googleapis/api/httpbody
 google.golang.org/genproto/googleapis/api/label
 google.golang.org/genproto/googleapis/api/metric
 google.golang.org/genproto/googleapis/api/monitoredres
-# google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f
-## explicit; go 1.22
+# google.golang.org/genproto/googleapis/rpc v0.0.0-20250219182151-9fdb1cabc7b2
+## explicit; go 1.23.0
 google.golang.org/genproto/googleapis/rpc/code
 google.golang.org/genproto/googleapis/rpc/errdetails
 google.golang.org/genproto/googleapis/rpc/status
@@ -1191,7 +1197,7 @@ google.golang.org/grpc/xds/internal/xdsclient/xdslbregistry
 google.golang.org/grpc/xds/internal/xdsclient/xdslbregistry/converter
 google.golang.org/grpc/xds/internal/xdsclient/xdsresource
 google.golang.org/grpc/xds/internal/xdsclient/xdsresource/version
-# google.golang.org/protobuf v1.36.4
+# google.golang.org/protobuf v1.36.5
 ## explicit; go 1.21
 google.golang.org/protobuf/encoding/protodelim
 google.golang.org/protobuf/encoding/protojson