Skip to content

Commit

Permalink
feat: generate type definition package godoc (#142)
Browse files Browse the repository at this point in the history
  • Loading branch information
grayside authored Jan 31, 2023
1 parent 4d9f2db commit b9e2108
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 9 deletions.
12 changes: 3 additions & 9 deletions generate-code.sh
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,6 @@ _generateValidationTests() {
return
fi

echo "- ${product}: ${proto_src} => ${code_dest}data${version}/data_test.go"

$GENERATE_PROTOC_PATH --go-googlecetypes_out=. \
--go-googlecetypes_opt="Mgoogle/events/cloudevent.proto"="github.com/googleapis/google-cloudevents-go/thirdparty/cloudevents;cloudevents" \
--go-googlecetypes_opt="M${proto_src}"="${code_dest}data${version}" \
Expand All @@ -175,15 +173,11 @@ for i in $(find "${GENERATE_DATA_SOURCE}/proto" -type f -name data.proto); do
_generateData "$i"
done

_heading "Generating validation tests..."
_heading "Generating validation tests and godoc..."
for i in $(find "${GENERATE_DATA_SOURCE}/proto" -type f -name events.proto); do
_generateValidationTests "$i"
done

_heading "Running validation tests..."
go test -v ./...

_heading "Running example tests..."
pushd examples >/dev/null
go test -v ./...
popd >/dev/null
# Run with GOFLAGS="-v" for verbose output.
go test ./...
87 changes: 87 additions & 0 deletions generators/protoc-gen-go-googlecetypes/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,21 @@ import (
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"text/template"

"google.golang.org/protobuf/compiler/protogen"
"google.golang.org/protobuf/reflect/protoreflect"
)

const TypePrefix = "google.events."
const SrcPrefix = "google/events/"

func main() {
log.SetOutput(os.Stderr)
log.SetFlags(0)

protogen.Options{}.Run(func(gen *protogen.Plugin) error {
for _, f := range gen.Files {
if !f.Generate {
Expand All @@ -30,6 +35,7 @@ func main() {
}

generateTests(gen, f)
generateDocs(gen, f)

}
return nil
Expand Down Expand Up @@ -152,5 +158,86 @@ func generateTests(gen *protogen.Plugin, file *protogen.File) *protogen.Generate
g.P(b.String())
b.Reset()

logGeneratedFileFromProto(file, filename)

return g
}

// generateDocs generates package docs.
func generateDocs(gen *protogen.Plugin, file *protogen.File) *protogen.GeneratedFile {
filename := filepath.Join(filepath.Dir(file.GeneratedFilenamePrefix), "doc.go")
g := gen.NewGeneratedFile(filename, file.GoImportPath)

product := getCustomField(gen, file.Desc.Options(), "cloud_event_product")
if product == "" {
panic("could not parse product name")
}
g.P("// Package ", string(file.GoPackageName), " provides ", product, " type definitions for CloudEvent data payloads.")
g.P("//")
g.P("// # Supported CloudEvent Types")
g.P("//")
for _, msg := range file.Messages {
// Access the comment describing the event type:
// d := strings.TrimSpace(strings.TrimPrefix(msg.Comments.Leading.String(), "// "))
t := getCustomField(gen, msg.Desc.Options(), "cloud_event_type")
if t != "" {
g.P("// - ", t)
}
}

g.P("package ", string(file.GoPackageName))

logGeneratedFileFromProto(file, filename)

return g
}

// getCustomField retrieves a field defined in the google/events/cloud_event.proto.
// Custom options are complex to reflect:
// - https://github.com/golang/protobuf/issues/1260.
// - https://github.com/jhump/protoreflect/issues/377
//
// This approach renders all options to a string then parses the value based on
// looking up the field number assigned in the extension descriptor.
func getCustomField(gen *protogen.Plugin, options protoreflect.ProtoMessage, name string) string {
var id int
for _, file := range gen.Request.ProtoFile {
if *file.Name != "google/events/cloudevent.proto" {
continue
}
for _, ext := range file.GetExtension() {
if *ext.Name == name {
id = int(*ext.Number)
break
}
}
}

return parseValueFromOptions(options, strconv.Itoa(id))
}

// parseValueFromOptionString extracts the value associated with a particular
// field number from the Stringified options.
func parseValueFromOptions(o protoreflect.ProtoMessage, id string) string {
// Example section of s: 11716487:\"API Gateway\"
s := fmt.Sprintf("%v", o)
// Split on the options ID.
a := strings.Split(s, id)
if len(a) < 2 {
return ""
}

// Data is formatted as the value in the next set of doublequotes.
b := strings.Split(a[1], `"`)
if len(b) < 2 {
return ""
}

return b[1]
}

func logGeneratedFileFromProto(file *protogen.File, filename string) {
re := regexp.MustCompile("^(.+)data")
m := re.FindStringSubmatch(string(file.GoPackageName))
log.Printf("- %s: %s => %s", m[1], file.Desc.Path(), filename)
}

0 comments on commit b9e2108

Please sign in to comment.