compiler/protogen: allow overriding API level from --go_opt

For golang/protobuf#1657

In order to change the default API level, one can now specify:

    protoc […] --go_opt=default_api_level=API_HYBRID

To override the default API level for a specific file, use
the apilevelM mapping flag (similar to the M flag for import paths):

    protoc […] --go_opt=apilevelMhello.proto=API_HYBRID

(Similar to the M option.)

Change-Id: I44590e9aa4c034a5bb9c93ae32f4b11188e684a0
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/634818
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
Michael Stapelberg 2024-12-06 10:44:38 +01:00
parent b64efdbc6e
commit 560503ec5d

View File

@ -185,6 +185,7 @@ func (opts Options) New(req *pluginpb.CodeGeneratorRequest) (*Plugin, error) {
packageNames := make(map[string]GoPackageName) // filename -> package name
importPaths := make(map[string]GoImportPath) // filename -> import path
apiLevel := make(map[string]gofeaturespb.GoFeatures_APILevel) // filename -> api level
for _, param := range strings.Split(req.GetParameter(), ",") {
var value string
if i := strings.Index(param, "="); i >= 0 {
@ -213,6 +214,18 @@ func (opts Options) New(req *pluginpb.CodeGeneratorRequest) (*Plugin, error) {
default:
return nil, fmt.Errorf(`bad value for parameter %q: want "true" or "false"`, param)
}
case "default_api_level":
switch value {
case "API_OPEN":
opts.DefaultAPILevel = gofeaturespb.GoFeatures_API_OPEN
case "API_HYBRID":
opts.DefaultAPILevel = gofeaturespb.GoFeatures_API_HYBRID
case "API_OPAQUE":
opts.DefaultAPILevel = gofeaturespb.GoFeatures_API_OPAQUE
default:
return nil, fmt.Errorf(`unknown API level %q for parameter %q: want "API_OPEN", "API_HYBRID" or "API_OPAQUE"`, value, param)
}
gen.opts = opts
default:
if param[0] == 'M' {
impPath, pkgName := splitImportPathAndPackageName(value)
@ -224,6 +237,21 @@ func (opts Options) New(req *pluginpb.CodeGeneratorRequest) (*Plugin, error) {
}
continue
}
if strings.HasPrefix(param, "apilevelM") {
var level gofeaturespb.GoFeatures_APILevel
switch value {
case "API_OPEN":
level = gofeaturespb.GoFeatures_API_OPEN
case "API_HYBRID":
level = gofeaturespb.GoFeatures_API_HYBRID
case "API_OPAQUE":
level = gofeaturespb.GoFeatures_API_OPAQUE
default:
return nil, fmt.Errorf(`unknown API level %q for parameter %q: want "API_OPEN", "API_HYBRID" or "API_OPAQUE"`, value, param)
}
apiLevel[strings.TrimPrefix(param, "apilevelM")] = level
continue
}
if opts.ParamFunc != nil {
if err := opts.ParamFunc(param, value); err != nil {
return nil, err
@ -328,7 +356,7 @@ func (opts Options) New(req *pluginpb.CodeGeneratorRequest) (*Plugin, error) {
if gen.FilesByPath[filename] != nil {
return nil, fmt.Errorf("duplicate file name: %q", filename)
}
f, err := newFile(gen, fdesc, packageNames[filename], importPaths[filename])
f, err := newFile(gen, fdesc, packageNames[filename], importPaths[filename], apiLevel[filename])
if err != nil {
return nil, err
}
@ -469,7 +497,7 @@ type File struct {
APILevel gofeaturespb.GoFeatures_APILevel
}
func newFile(gen *Plugin, p *descriptorpb.FileDescriptorProto, packageName GoPackageName, importPath GoImportPath) (*File, error) {
func newFile(gen *Plugin, p *descriptorpb.FileDescriptorProto, packageName GoPackageName, importPath GoImportPath, apiLevel gofeaturespb.GoFeatures_APILevel) (*File, error) {
desc, err := protodesc.NewFile(p, gen.fileReg)
if err != nil {
return nil, fmt.Errorf("invalid FileDescriptorProto %q: %v", p.GetName(), err)
@ -477,6 +505,10 @@ func newFile(gen *Plugin, p *descriptorpb.FileDescriptorProto, packageName GoPac
if err := gen.fileReg.RegisterFile(desc); err != nil {
return nil, fmt.Errorf("cannot register descriptor %q: %v", p.GetName(), err)
}
defaultAPILevel := gen.defaultAPILevel()
if apiLevel != gofeaturespb.GoFeatures_API_LEVEL_UNSPECIFIED {
defaultAPILevel = apiLevel
}
f := &File{
Desc: desc,
Proto: p,
@ -484,7 +516,7 @@ func newFile(gen *Plugin, p *descriptorpb.FileDescriptorProto, packageName GoPac
GoImportPath: importPath,
location: Location{SourceFile: desc.Path()},
APILevel: fileAPILevel(desc, gen.defaultAPILevel()),
APILevel: fileAPILevel(desc, defaultAPILevel),
}
// Determine the prefix for generated Go files.