diff --git a/cmd/protoc-gen-go/internal_gengo/main.go b/cmd/protoc-gen-go/internal_gengo/main.go index 69e4aeca..40e5f050 100644 --- a/cmd/protoc-gen-go/internal_gengo/main.go +++ b/cmd/protoc-gen-go/internal_gengo/main.go @@ -17,6 +17,7 @@ import ( "unicode/utf8" "google.golang.org/protobuf/compiler/protogen" + "google.golang.org/protobuf/internal/editionssupport" "google.golang.org/protobuf/internal/encoding/tag" "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/internal/genid" @@ -29,7 +30,10 @@ import ( ) // SupportedFeatures reports the set of supported protobuf language features. -var SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL) +var SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL | pluginpb.CodeGeneratorResponse_FEATURE_SUPPORTS_EDITIONS) + +var SupportedEditionsMinimum = editionssupport.Minimum +var SupportedEditionsMaximum = editionssupport.Maximum // GenerateVersionMarkers specifies whether to generate version markers. var GenerateVersionMarkers = true diff --git a/compiler/protogen/protogen.go b/compiler/protogen/protogen.go index 914c57b1..7a43a011 100644 --- a/compiler/protogen/protogen.go +++ b/compiler/protogen/protogen.go @@ -108,6 +108,9 @@ type Plugin struct { // google.protobuf.CodeGeneratorResponse.supported_features for details. SupportedFeatures uint64 + SupportedEditionsMinimum descriptorpb.Edition + SupportedEditionsMaximum descriptorpb.Edition + fileReg *protoregistry.Files enumsByName map[protoreflect.FullName]*Enum messagesByName map[protoreflect.FullName]*Message @@ -396,6 +399,10 @@ func (gen *Plugin) Response() *pluginpb.CodeGeneratorResponse { if gen.SupportedFeatures > 0 { resp.SupportedFeatures = proto.Uint64(gen.SupportedFeatures) } + if gen.SupportedEditionsMinimum != descriptorpb.Edition_EDITION_UNKNOWN && gen.SupportedEditionsMaximum != descriptorpb.Edition_EDITION_UNKNOWN { + resp.MinimumEdition = proto.Int32(int32(gen.SupportedEditionsMinimum)) + resp.MaximumEdition = proto.Int32(int32(gen.SupportedEditionsMaximum)) + } return resp } diff --git a/internal/cmd/generate-protos/main.go b/internal/cmd/generate-protos/main.go index b8720d7f..14bfc23e 100644 --- a/internal/cmd/generate-protos/main.go +++ b/internal/cmd/generate-protos/main.go @@ -24,7 +24,7 @@ import ( gengo "google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo" "google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/internal/detrand" - "google.golang.org/protobuf/reflect/protodesc" + "google.golang.org/protobuf/internal/editionssupport" ) func init() { @@ -108,8 +108,8 @@ func generateEditionsDefaults() { // The enum in Go string formats to "EDITION_${EDITION}" but protoc expects // the flag in the form "${EDITION}". To work around this, we trim the // "EDITION_" prefix. - minEdition := strings.TrimPrefix(fmt.Sprint(protodesc.SupportedEditionsMinimum), "EDITION_") - maxEdition := strings.TrimPrefix(fmt.Sprint(protodesc.SupportedEditionsMaximum), "EDITION_") + minEdition := strings.TrimPrefix(fmt.Sprint(editionssupport.Minimum), "EDITION_") + maxEdition := strings.TrimPrefix(fmt.Sprint(editionssupport.Maximum), "EDITION_") cmd := exec.Command( "protoc", "--experimental_edition_defaults_out", dest, diff --git a/internal/editionssupport/editions.go b/internal/editionssupport/editions.go new file mode 100644 index 00000000..029a6a12 --- /dev/null +++ b/internal/editionssupport/editions.go @@ -0,0 +1,13 @@ +// 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 editionssupport defines constants for editions that are supported. +package editionssupport + +import descriptorpb "google.golang.org/protobuf/types/descriptorpb" + +const ( + Minimum = descriptorpb.Edition_EDITION_PROTO2 + Maximum = descriptorpb.Edition_EDITION_2023 +) diff --git a/internal/filedesc/desc.go b/internal/filedesc/desc.go index 54122e0c..903e9cd4 100644 --- a/internal/filedesc/desc.go +++ b/internal/filedesc/desc.go @@ -333,8 +333,7 @@ func (fd *Field) HasPresence() bool { if fd.L1.Cardinality == protoreflect.Repeated { return false } - explicitFieldPresence := fd.Syntax() == protoreflect.Editions && fd.L1.EditionFeatures.IsFieldPresence - return fd.Syntax() == protoreflect.Proto2 || explicitFieldPresence || fd.L1.Message != nil || fd.L1.ContainingOneof != nil + return fd.L1.EditionFeatures.IsFieldPresence || fd.L1.Message != nil || fd.L1.ContainingOneof != nil } func (fd *Field) HasOptionalKeyword() bool { return (fd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 && fd.L1.Cardinality == protoreflect.Optional && fd.L1.ContainingOneof == nil) || fd.L1.IsProto3Optional diff --git a/reflect/protodesc/desc.go b/reflect/protodesc/desc.go index 6813d6b8..8fbecb4f 100644 --- a/reflect/protodesc/desc.go +++ b/reflect/protodesc/desc.go @@ -13,6 +13,7 @@ package protodesc import ( + "google.golang.org/protobuf/internal/editionssupport" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/internal/pragma" @@ -101,7 +102,7 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot default: return nil, errors.New("invalid syntax: %q", fd.GetSyntax()) } - if f.L1.Syntax == protoreflect.Editions && (fd.GetEdition() < SupportedEditionsMinimum || fd.GetEdition() > SupportedEditionsMaximum) { + if f.L1.Syntax == protoreflect.Editions && (fd.GetEdition() < editionssupport.Minimum || fd.GetEdition() > editionssupport.Maximum) { return nil, errors.New("use of edition %v not yet supported by the Go Protobuf runtime", fd.GetEdition()) } f.L1.Path = fd.GetName() diff --git a/reflect/protodesc/editions.go b/reflect/protodesc/editions.go index 2a6b29d1..f6a1fec6 100644 --- a/reflect/protodesc/editions.go +++ b/reflect/protodesc/editions.go @@ -17,11 +17,6 @@ import ( gofeaturespb "google.golang.org/protobuf/types/gofeaturespb" ) -const ( - SupportedEditionsMinimum = descriptorpb.Edition_EDITION_PROTO2 - SupportedEditionsMaximum = descriptorpb.Edition_EDITION_2023 -) - var defaults = &descriptorpb.FeatureSetDefaults{} var defaultsCacheMu sync.Mutex var defaultsCache = make(map[filedesc.Edition]*descriptorpb.FeatureSet)