Skip to content

Commit

Permalink
Support 'optional' fields in proto3 (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
wyattanderson authored Nov 8, 2022
1 parent c6ad161 commit ea7f077
Show file tree
Hide file tree
Showing 10 changed files with 2,753 additions and 48 deletions.
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,5 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
93 changes: 47 additions & 46 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,63 +1,64 @@
package main

import (
"errors"
"flag"
"fmt"
"io"
"os"
"strings"

"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/compiler/protogen"
"google.golang.org/protobuf/types/pluginpb"

"github.com/ckaznocha/protoc-gen-lint/linter"
)

// SortImports represents the parameter, which can be specified to the tool invocation
// to enable checking, whether the proto file imports are sorted alphabetically.
const SortImports = "sort_imports"
type BoolFlag interface {
IsBoolFlag() bool
}

var errLint = errors.New("encountered lint errors")

func main() {
var (
totalErrors int
generatorRequest pluginpb.CodeGeneratorRequest
parameters struct {
SortImports bool
}
)

data, err := io.ReadAll(os.Stdin)
if err != nil {
panic(err)
}

if err := proto.Unmarshal(data, &generatorRequest); err != nil {
panic(err)
}

for _, p := range strings.Split(generatorRequest.GetParameter(), ",") {
switch strings.TrimSpace(p) {
case "":
continue
case SortImports:
parameters.SortImports = true
default:
fmt.Fprintf(os.Stderr, "Unmatched parameter: %s", p)
os.Exit(1)
}
}

for _, file := range generatorRequest.GetProtoFile() {
numErrors, err := linter.LintProtoFile(linter.Config{
ProtoFile: file,
OutFile: os.Stderr,
SortImports: parameters.SortImports,
})
if err != nil {
panic(err)
var flags flag.FlagSet
sortImports := flags.Bool("sort_imports", false, "check whether or not the proto "+
"file imports are sorted alphabetically")

protogen.Options{
ParamFunc: func(param, value string) error {
// For backwards compatibility, treat a present flag with an empty
// string value as boolean true. The Go flag module parsing
// handles this, but the protogen flag parse behavior doesn't,
// because it doesn't parse flags the same way.
f := flags.Lookup(param)
if f != nil {
if _, ok := f.Value.(BoolFlag); ok {
value = "true"
}
}

return flags.Set(param, value)
},
}.Run(func(gen *protogen.Plugin) error {
gen.SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL)

totalErrors := 0
for _, f := range gen.Files {
numErrors, err := linter.LintProtoFile(linter.Config{
ProtoFile: f.Proto,
OutFile: os.Stderr,
SortImports: *sortImports,
})
if err != nil {
return err
}

totalErrors += numErrors
}

totalErrors += numErrors
}
if totalErrors > 0 {
return fmt.Errorf("%w: %d total", errLint, totalErrors)
}

os.Exit(totalErrors)
return nil
})
}
7 changes: 7 additions & 0 deletions optional.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
syntax = "proto3";

package test.optional;

message WithOptional {
optional string test = 1;
}
Loading

0 comments on commit ea7f077

Please sign in to comment.