1*1c12ee1eSDan Willemsen// Copyright 2019 The Go Authors. All rights reserved. 2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style 3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file. 4*1c12ee1eSDan Willemsen 5*1c12ee1eSDan Willemsen//go:generate go run . -execute 6*1c12ee1eSDan Willemsen 7*1c12ee1eSDan Willemsenpackage main 8*1c12ee1eSDan Willemsen 9*1c12ee1eSDan Willemsenimport ( 10*1c12ee1eSDan Willemsen "bytes" 11*1c12ee1eSDan Willemsen "flag" 12*1c12ee1eSDan Willemsen "fmt" 13*1c12ee1eSDan Willemsen "go/format" 14*1c12ee1eSDan Willemsen "io/ioutil" 15*1c12ee1eSDan Willemsen "os" 16*1c12ee1eSDan Willemsen "os/exec" 17*1c12ee1eSDan Willemsen "path" 18*1c12ee1eSDan Willemsen "path/filepath" 19*1c12ee1eSDan Willemsen "regexp" 20*1c12ee1eSDan Willemsen "sort" 21*1c12ee1eSDan Willemsen "strconv" 22*1c12ee1eSDan Willemsen "strings" 23*1c12ee1eSDan Willemsen 24*1c12ee1eSDan Willemsen gengo "google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo" 25*1c12ee1eSDan Willemsen "google.golang.org/protobuf/compiler/protogen" 26*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/detrand" 27*1c12ee1eSDan Willemsen) 28*1c12ee1eSDan Willemsen 29*1c12ee1eSDan Willemsenfunc init() { 30*1c12ee1eSDan Willemsen // Determine repository root path. 31*1c12ee1eSDan Willemsen out, err := exec.Command("git", "rev-parse", "--show-toplevel").CombinedOutput() 32*1c12ee1eSDan Willemsen check(err) 33*1c12ee1eSDan Willemsen repoRoot = strings.TrimSpace(string(out)) 34*1c12ee1eSDan Willemsen 35*1c12ee1eSDan Willemsen // Determine the module path. 36*1c12ee1eSDan Willemsen cmd := exec.Command("go", "list", "-m", "-f", "{{.Path}}") 37*1c12ee1eSDan Willemsen cmd.Dir = repoRoot 38*1c12ee1eSDan Willemsen out, err = cmd.CombinedOutput() 39*1c12ee1eSDan Willemsen check(err) 40*1c12ee1eSDan Willemsen modulePath = strings.TrimSpace(string(out)) 41*1c12ee1eSDan Willemsen 42*1c12ee1eSDan Willemsen // When the environment variable RUN_AS_PROTOC_PLUGIN is set, 43*1c12ee1eSDan Willemsen // we skip running main and instead act as a protoc plugin. 44*1c12ee1eSDan Willemsen // This allows the binary to pass itself to protoc. 45*1c12ee1eSDan Willemsen if plugin := os.Getenv("RUN_AS_PROTOC_PLUGIN"); plugin != "" { 46*1c12ee1eSDan Willemsen // Disable deliberate output instability for generated files. 47*1c12ee1eSDan Willemsen // This is reasonable since we fully control the output. 48*1c12ee1eSDan Willemsen detrand.Disable() 49*1c12ee1eSDan Willemsen 50*1c12ee1eSDan Willemsen protogen.Options{}.Run(func(gen *protogen.Plugin) error { 51*1c12ee1eSDan Willemsen for _, file := range gen.Files { 52*1c12ee1eSDan Willemsen if file.Generate { 53*1c12ee1eSDan Willemsen gengo.GenerateVersionMarkers = false 54*1c12ee1eSDan Willemsen gengo.GenerateFile(gen, file) 55*1c12ee1eSDan Willemsen generateIdentifiers(gen, file) 56*1c12ee1eSDan Willemsen generateSourceContextStringer(gen, file) 57*1c12ee1eSDan Willemsen } 58*1c12ee1eSDan Willemsen } 59*1c12ee1eSDan Willemsen gen.SupportedFeatures = gengo.SupportedFeatures 60*1c12ee1eSDan Willemsen return nil 61*1c12ee1eSDan Willemsen }) 62*1c12ee1eSDan Willemsen os.Exit(0) 63*1c12ee1eSDan Willemsen } 64*1c12ee1eSDan Willemsen} 65*1c12ee1eSDan Willemsen 66*1c12ee1eSDan Willemsenvar ( 67*1c12ee1eSDan Willemsen run bool 68*1c12ee1eSDan Willemsen protoRoot string 69*1c12ee1eSDan Willemsen repoRoot string 70*1c12ee1eSDan Willemsen modulePath string 71*1c12ee1eSDan Willemsen 72*1c12ee1eSDan Willemsen generatedPreamble = []string{ 73*1c12ee1eSDan Willemsen "// Copyright 2019 The Go Authors. All rights reserved.", 74*1c12ee1eSDan Willemsen "// Use of this source code is governed by a BSD-style", 75*1c12ee1eSDan Willemsen "// license that can be found in the LICENSE file.", 76*1c12ee1eSDan Willemsen "", 77*1c12ee1eSDan Willemsen "// Code generated by generate-protos. DO NOT EDIT.", 78*1c12ee1eSDan Willemsen "", 79*1c12ee1eSDan Willemsen } 80*1c12ee1eSDan Willemsen) 81*1c12ee1eSDan Willemsen 82*1c12ee1eSDan Willemsenfunc main() { 83*1c12ee1eSDan Willemsen flag.BoolVar(&run, "execute", false, "Write generated files to destination.") 84*1c12ee1eSDan Willemsen flag.StringVar(&protoRoot, "protoroot", os.Getenv("PROTOBUF_ROOT"), "The root of the protobuf source tree.") 85*1c12ee1eSDan Willemsen flag.Parse() 86*1c12ee1eSDan Willemsen if protoRoot == "" { 87*1c12ee1eSDan Willemsen panic("protobuf source root is not set") 88*1c12ee1eSDan Willemsen } 89*1c12ee1eSDan Willemsen 90*1c12ee1eSDan Willemsen generateLocalProtos() 91*1c12ee1eSDan Willemsen generateRemoteProtos() 92*1c12ee1eSDan Willemsen} 93*1c12ee1eSDan Willemsen 94*1c12ee1eSDan Willemsenfunc generateLocalProtos() { 95*1c12ee1eSDan Willemsen tmpDir, err := ioutil.TempDir(repoRoot, "tmp") 96*1c12ee1eSDan Willemsen check(err) 97*1c12ee1eSDan Willemsen defer os.RemoveAll(tmpDir) 98*1c12ee1eSDan Willemsen 99*1c12ee1eSDan Willemsen // Generate all local proto files (except version-locked files). 100*1c12ee1eSDan Willemsen dirs := []struct { 101*1c12ee1eSDan Willemsen path string 102*1c12ee1eSDan Willemsen pkgPaths map[string]string // mapping of .proto path to Go package path 103*1c12ee1eSDan Willemsen annotate map[string]bool // .proto files to annotate 104*1c12ee1eSDan Willemsen exclude map[string]bool // .proto files to exclude from generation 105*1c12ee1eSDan Willemsen }{{ 106*1c12ee1eSDan Willemsen path: "cmd/protoc-gen-go/testdata", 107*1c12ee1eSDan Willemsen pkgPaths: map[string]string{"cmd/protoc-gen-go/testdata/nopackage/nopackage.proto": "google.golang.org/protobuf/cmd/protoc-gen-go/testdata/nopackage"}, 108*1c12ee1eSDan Willemsen annotate: map[string]bool{"cmd/protoc-gen-go/testdata/annotations/annotations.proto": true}, 109*1c12ee1eSDan Willemsen }, { 110*1c12ee1eSDan Willemsen path: "internal/testprotos", 111*1c12ee1eSDan Willemsen exclude: map[string]bool{"internal/testprotos/irregular/irregular.proto": true}, 112*1c12ee1eSDan Willemsen }} 113*1c12ee1eSDan Willemsen excludeRx := regexp.MustCompile(`legacy/.*/`) 114*1c12ee1eSDan Willemsen for _, d := range dirs { 115*1c12ee1eSDan Willemsen subDirs := map[string]bool{} 116*1c12ee1eSDan Willemsen 117*1c12ee1eSDan Willemsen srcDir := filepath.Join(repoRoot, filepath.FromSlash(d.path)) 118*1c12ee1eSDan Willemsen filepath.Walk(srcDir, func(srcPath string, _ os.FileInfo, _ error) error { 119*1c12ee1eSDan Willemsen if !strings.HasSuffix(srcPath, ".proto") || excludeRx.MatchString(srcPath) { 120*1c12ee1eSDan Willemsen return nil 121*1c12ee1eSDan Willemsen } 122*1c12ee1eSDan Willemsen relPath, err := filepath.Rel(repoRoot, srcPath) 123*1c12ee1eSDan Willemsen check(err) 124*1c12ee1eSDan Willemsen 125*1c12ee1eSDan Willemsen srcRelPath, err := filepath.Rel(srcDir, srcPath) 126*1c12ee1eSDan Willemsen check(err) 127*1c12ee1eSDan Willemsen subDirs[filepath.Dir(srcRelPath)] = true 128*1c12ee1eSDan Willemsen 129*1c12ee1eSDan Willemsen if d.exclude[filepath.ToSlash(relPath)] { 130*1c12ee1eSDan Willemsen return nil 131*1c12ee1eSDan Willemsen } 132*1c12ee1eSDan Willemsen 133*1c12ee1eSDan Willemsen opts := "module=" + modulePath 134*1c12ee1eSDan Willemsen for protoPath, goPkgPath := range d.pkgPaths { 135*1c12ee1eSDan Willemsen opts += fmt.Sprintf(",M%v=%v", protoPath, goPkgPath) 136*1c12ee1eSDan Willemsen } 137*1c12ee1eSDan Willemsen if d.annotate[filepath.ToSlash(relPath)] { 138*1c12ee1eSDan Willemsen opts += ",annotate_code" 139*1c12ee1eSDan Willemsen } 140*1c12ee1eSDan Willemsen protoc("-I"+filepath.Join(protoRoot, "src"), "-I"+repoRoot, "--go_out="+opts+":"+tmpDir, relPath) 141*1c12ee1eSDan Willemsen return nil 142*1c12ee1eSDan Willemsen }) 143*1c12ee1eSDan Willemsen 144*1c12ee1eSDan Willemsen // For directories in testdata, generate a test that links in all 145*1c12ee1eSDan Willemsen // generated packages to ensure that it builds and initializes properly. 146*1c12ee1eSDan Willemsen // This is done because "go build ./..." does not build sub-packages 147*1c12ee1eSDan Willemsen // under testdata. 148*1c12ee1eSDan Willemsen if filepath.Base(d.path) == "testdata" { 149*1c12ee1eSDan Willemsen var imports []string 150*1c12ee1eSDan Willemsen for sd := range subDirs { 151*1c12ee1eSDan Willemsen imports = append(imports, fmt.Sprintf("_ %q", path.Join(modulePath, d.path, filepath.ToSlash(sd)))) 152*1c12ee1eSDan Willemsen } 153*1c12ee1eSDan Willemsen sort.Strings(imports) 154*1c12ee1eSDan Willemsen 155*1c12ee1eSDan Willemsen s := strings.Join(append(generatedPreamble, []string{ 156*1c12ee1eSDan Willemsen "package main", 157*1c12ee1eSDan Willemsen "", 158*1c12ee1eSDan Willemsen "import (" + strings.Join(imports, "\n") + ")", 159*1c12ee1eSDan Willemsen }...), "\n") 160*1c12ee1eSDan Willemsen b, err := format.Source([]byte(s)) 161*1c12ee1eSDan Willemsen check(err) 162*1c12ee1eSDan Willemsen check(ioutil.WriteFile(filepath.Join(tmpDir, filepath.FromSlash(d.path+"/gen_test.go")), b, 0664)) 163*1c12ee1eSDan Willemsen } 164*1c12ee1eSDan Willemsen } 165*1c12ee1eSDan Willemsen 166*1c12ee1eSDan Willemsen syncOutput(repoRoot, tmpDir) 167*1c12ee1eSDan Willemsen} 168*1c12ee1eSDan Willemsen 169*1c12ee1eSDan Willemsenfunc generateRemoteProtos() { 170*1c12ee1eSDan Willemsen tmpDir, err := ioutil.TempDir(repoRoot, "tmp") 171*1c12ee1eSDan Willemsen check(err) 172*1c12ee1eSDan Willemsen defer os.RemoveAll(tmpDir) 173*1c12ee1eSDan Willemsen 174*1c12ee1eSDan Willemsen // Generate all remote proto files. 175*1c12ee1eSDan Willemsen files := []struct{ prefix, path, goPkgPath string }{ 176*1c12ee1eSDan Willemsen // Well-known protos. 177*1c12ee1eSDan Willemsen {"src", "google/protobuf/any.proto", ""}, 178*1c12ee1eSDan Willemsen {"src", "google/protobuf/api.proto", ""}, 179*1c12ee1eSDan Willemsen {"src", "google/protobuf/duration.proto", ""}, 180*1c12ee1eSDan Willemsen {"src", "google/protobuf/empty.proto", ""}, 181*1c12ee1eSDan Willemsen {"src", "google/protobuf/field_mask.proto", ""}, 182*1c12ee1eSDan Willemsen {"src", "google/protobuf/source_context.proto", ""}, 183*1c12ee1eSDan Willemsen {"src", "google/protobuf/struct.proto", ""}, 184*1c12ee1eSDan Willemsen {"src", "google/protobuf/timestamp.proto", ""}, 185*1c12ee1eSDan Willemsen {"src", "google/protobuf/type.proto", ""}, 186*1c12ee1eSDan Willemsen {"src", "google/protobuf/wrappers.proto", ""}, 187*1c12ee1eSDan Willemsen 188*1c12ee1eSDan Willemsen // Compiler protos. 189*1c12ee1eSDan Willemsen {"src", "google/protobuf/compiler/plugin.proto", ""}, 190*1c12ee1eSDan Willemsen {"src", "google/protobuf/descriptor.proto", ""}, 191*1c12ee1eSDan Willemsen 192*1c12ee1eSDan Willemsen // Conformance protos. 193*1c12ee1eSDan Willemsen {"", "conformance/conformance.proto", "google.golang.org/protobuf/internal/testprotos/conformance;conformance"}, 194*1c12ee1eSDan Willemsen {"src", "google/protobuf/test_messages_proto2.proto", "google.golang.org/protobuf/internal/testprotos/conformance;conformance"}, 195*1c12ee1eSDan Willemsen {"src", "google/protobuf/test_messages_proto3.proto", "google.golang.org/protobuf/internal/testprotos/conformance;conformance"}, 196*1c12ee1eSDan Willemsen 197*1c12ee1eSDan Willemsen // Benchmark protos. 198*1c12ee1eSDan Willemsen // TODO: The protobuf repo no longer includes benchmarks. 199*1c12ee1eSDan Willemsen // CL removing them says they are superceded by google/fleetbench: 200*1c12ee1eSDan Willemsen // https://github.com/protocolbuffers/protobuf/commit/83c499de86224538e5d59adc3d0fa7fdb45b2c72 201*1c12ee1eSDan Willemsen // But that project's proto benchmark files are very different: 202*1c12ee1eSDan Willemsen // https://github.com/google/fleetbench/tree/main/fleetbench/proto 203*1c12ee1eSDan Willemsen // For now, commenting these out until benchmarks in this repo can be 204*1c12ee1eSDan Willemsen // reconciled with new fleetbench stuff. 205*1c12ee1eSDan Willemsen //{"benchmarks", "benchmarks.proto", "google.golang.org/protobuf/internal/testprotos/benchmarks;benchmarks"}, 206*1c12ee1eSDan Willemsen //{"benchmarks", "datasets/google_message1/proto2/benchmark_message1_proto2.proto", "google.golang.org/protobuf/internal/testprotos/benchmarks/datasets/google_message1/proto2;proto2"}, 207*1c12ee1eSDan Willemsen //{"benchmarks", "datasets/google_message1/proto3/benchmark_message1_proto3.proto", "google.golang.org/protobuf/internal/testprotos/benchmarks/datasets/google_message1/proto3;proto3"}, 208*1c12ee1eSDan Willemsen //{"benchmarks", "datasets/google_message2/benchmark_message2.proto", "google.golang.org/protobuf/internal/testprotos/benchmarks/datasets/google_message2;google_message2"}, 209*1c12ee1eSDan Willemsen //{"benchmarks", "datasets/google_message3/benchmark_message3.proto", "google.golang.org/protobuf/internal/testprotos/benchmarks/datasets/google_message3;google_message3"}, 210*1c12ee1eSDan Willemsen //{"benchmarks", "datasets/google_message3/benchmark_message3_1.proto", "google.golang.org/protobuf/internal/testprotos/benchmarks/datasets/google_message3;google_message3"}, 211*1c12ee1eSDan Willemsen //{"benchmarks", "datasets/google_message3/benchmark_message3_2.proto", "google.golang.org/protobuf/internal/testprotos/benchmarks/datasets/google_message3;google_message3"}, 212*1c12ee1eSDan Willemsen //{"benchmarks", "datasets/google_message3/benchmark_message3_3.proto", "google.golang.org/protobuf/internal/testprotos/benchmarks/datasets/google_message3;google_message3"}, 213*1c12ee1eSDan Willemsen //{"benchmarks", "datasets/google_message3/benchmark_message3_4.proto", "google.golang.org/protobuf/internal/testprotos/benchmarks/datasets/google_message3;google_message3"}, 214*1c12ee1eSDan Willemsen //{"benchmarks", "datasets/google_message3/benchmark_message3_5.proto", "google.golang.org/protobuf/internal/testprotos/benchmarks/datasets/google_message3;google_message3"}, 215*1c12ee1eSDan Willemsen //{"benchmarks", "datasets/google_message3/benchmark_message3_6.proto", "google.golang.org/protobuf/internal/testprotos/benchmarks/datasets/google_message3;google_message3"}, 216*1c12ee1eSDan Willemsen //{"benchmarks", "datasets/google_message3/benchmark_message3_7.proto", "google.golang.org/protobuf/internal/testprotos/benchmarks/datasets/google_message3;google_message3"}, 217*1c12ee1eSDan Willemsen //{"benchmarks", "datasets/google_message3/benchmark_message3_8.proto", "google.golang.org/protobuf/internal/testprotos/benchmarks/datasets/google_message3;google_message3"}, 218*1c12ee1eSDan Willemsen //{"benchmarks", "datasets/google_message4/benchmark_message4.proto", "google.golang.org/protobuf/internal/testprotos/benchmarks/datasets/google_message4;google_message4"}, 219*1c12ee1eSDan Willemsen //{"benchmarks", "datasets/google_message4/benchmark_message4_1.proto", "google.golang.org/protobuf/internal/testprotos/benchmarks/datasets/google_message4;google_message4"}, 220*1c12ee1eSDan Willemsen //{"benchmarks", "datasets/google_message4/benchmark_message4_2.proto", "google.golang.org/protobuf/internal/testprotos/benchmarks/datasets/google_message4;google_message4"}, 221*1c12ee1eSDan Willemsen //{"benchmarks", "datasets/google_message4/benchmark_message4_3.proto", "google.golang.org/protobuf/internal/testprotos/benchmarks/datasets/google_message4;google_message4"}, 222*1c12ee1eSDan Willemsen } 223*1c12ee1eSDan Willemsen 224*1c12ee1eSDan Willemsen opts := "module=" + modulePath 225*1c12ee1eSDan Willemsen for _, file := range files { 226*1c12ee1eSDan Willemsen if file.goPkgPath != "" { 227*1c12ee1eSDan Willemsen opts += fmt.Sprintf(",M%v=%v", file.path, file.goPkgPath) 228*1c12ee1eSDan Willemsen } 229*1c12ee1eSDan Willemsen } 230*1c12ee1eSDan Willemsen for _, f := range files { 231*1c12ee1eSDan Willemsen protoc("-I"+filepath.Join(protoRoot, f.prefix), "--go_out="+opts+":"+tmpDir, f.path) 232*1c12ee1eSDan Willemsen } 233*1c12ee1eSDan Willemsen 234*1c12ee1eSDan Willemsen syncOutput(repoRoot, tmpDir) 235*1c12ee1eSDan Willemsen} 236*1c12ee1eSDan Willemsen 237*1c12ee1eSDan Willemsenfunc protoc(args ...string) { 238*1c12ee1eSDan Willemsen // TODO: Remove --experimental_allow_proto3_optional flag. 239*1c12ee1eSDan Willemsen cmd := exec.Command("protoc", "--plugin=protoc-gen-go="+os.Args[0], "--experimental_allow_proto3_optional") 240*1c12ee1eSDan Willemsen cmd.Args = append(cmd.Args, args...) 241*1c12ee1eSDan Willemsen cmd.Env = append(os.Environ(), "RUN_AS_PROTOC_PLUGIN=1") 242*1c12ee1eSDan Willemsen out, err := cmd.CombinedOutput() 243*1c12ee1eSDan Willemsen if err != nil { 244*1c12ee1eSDan Willemsen fmt.Printf("executing: %v\n%s\n", strings.Join(cmd.Args, " "), out) 245*1c12ee1eSDan Willemsen } 246*1c12ee1eSDan Willemsen check(err) 247*1c12ee1eSDan Willemsen} 248*1c12ee1eSDan Willemsen 249*1c12ee1eSDan Willemsen// generateIdentifiers generates an internal package for descriptor.proto 250*1c12ee1eSDan Willemsen// and well-known types. 251*1c12ee1eSDan Willemsenfunc generateIdentifiers(gen *protogen.Plugin, file *protogen.File) { 252*1c12ee1eSDan Willemsen if file.Desc.Package() != "google.protobuf" { 253*1c12ee1eSDan Willemsen return 254*1c12ee1eSDan Willemsen } 255*1c12ee1eSDan Willemsen 256*1c12ee1eSDan Willemsen importPath := modulePath + "/internal/genid" 257*1c12ee1eSDan Willemsen base := strings.TrimSuffix(path.Base(file.Desc.Path()), ".proto") 258*1c12ee1eSDan Willemsen g := gen.NewGeneratedFile(importPath+"/"+base+"_gen.go", protogen.GoImportPath(importPath)) 259*1c12ee1eSDan Willemsen for _, s := range generatedPreamble { 260*1c12ee1eSDan Willemsen g.P(s) 261*1c12ee1eSDan Willemsen } 262*1c12ee1eSDan Willemsen g.P("package ", path.Base(importPath)) 263*1c12ee1eSDan Willemsen g.P() 264*1c12ee1eSDan Willemsen 265*1c12ee1eSDan Willemsen g.P("const ", file.GoDescriptorIdent.GoName, " = ", strconv.Quote(file.Desc.Path())) 266*1c12ee1eSDan Willemsen g.P() 267*1c12ee1eSDan Willemsen 268*1c12ee1eSDan Willemsen var processEnums func([]*protogen.Enum) 269*1c12ee1eSDan Willemsen var processMessages func([]*protogen.Message) 270*1c12ee1eSDan Willemsen const protoreflectPackage = protogen.GoImportPath("google.golang.org/protobuf/reflect/protoreflect") 271*1c12ee1eSDan Willemsen processEnums = func(enums []*protogen.Enum) { 272*1c12ee1eSDan Willemsen for _, enum := range enums { 273*1c12ee1eSDan Willemsen g.P("// Full and short names for ", enum.Desc.FullName(), ".") 274*1c12ee1eSDan Willemsen g.P("const (") 275*1c12ee1eSDan Willemsen g.P(enum.GoIdent.GoName, "_enum_fullname = ", strconv.Quote(string(enum.Desc.FullName()))) 276*1c12ee1eSDan Willemsen g.P(enum.GoIdent.GoName, "_enum_name = ", strconv.Quote(string(enum.Desc.Name()))) 277*1c12ee1eSDan Willemsen g.P(")") 278*1c12ee1eSDan Willemsen g.P() 279*1c12ee1eSDan Willemsen } 280*1c12ee1eSDan Willemsen } 281*1c12ee1eSDan Willemsen processMessages = func(messages []*protogen.Message) { 282*1c12ee1eSDan Willemsen for _, message := range messages { 283*1c12ee1eSDan Willemsen g.P("// Names for ", message.Desc.FullName(), ".") 284*1c12ee1eSDan Willemsen g.P("const (") 285*1c12ee1eSDan Willemsen g.P(message.GoIdent.GoName, "_message_name ", protoreflectPackage.Ident("Name"), " = ", strconv.Quote(string(message.Desc.Name()))) 286*1c12ee1eSDan Willemsen g.P(message.GoIdent.GoName, "_message_fullname ", protoreflectPackage.Ident("FullName"), " = ", strconv.Quote(string(message.Desc.FullName()))) 287*1c12ee1eSDan Willemsen g.P(")") 288*1c12ee1eSDan Willemsen g.P() 289*1c12ee1eSDan Willemsen 290*1c12ee1eSDan Willemsen if len(message.Fields) > 0 { 291*1c12ee1eSDan Willemsen g.P("// Field names for ", message.Desc.FullName(), ".") 292*1c12ee1eSDan Willemsen g.P("const (") 293*1c12ee1eSDan Willemsen for _, field := range message.Fields { 294*1c12ee1eSDan Willemsen g.P(message.GoIdent.GoName, "_", field.GoName, "_field_name ", protoreflectPackage.Ident("Name"), " = ", strconv.Quote(string(field.Desc.Name()))) 295*1c12ee1eSDan Willemsen } 296*1c12ee1eSDan Willemsen g.P() 297*1c12ee1eSDan Willemsen for _, field := range message.Fields { 298*1c12ee1eSDan Willemsen g.P(message.GoIdent.GoName, "_", field.GoName, "_field_fullname ", protoreflectPackage.Ident("FullName"), " = ", strconv.Quote(string(field.Desc.FullName()))) 299*1c12ee1eSDan Willemsen } 300*1c12ee1eSDan Willemsen g.P(")") 301*1c12ee1eSDan Willemsen g.P() 302*1c12ee1eSDan Willemsen 303*1c12ee1eSDan Willemsen g.P("// Field numbers for ", message.Desc.FullName(), ".") 304*1c12ee1eSDan Willemsen g.P("const (") 305*1c12ee1eSDan Willemsen for _, field := range message.Fields { 306*1c12ee1eSDan Willemsen g.P(message.GoIdent.GoName, "_", field.GoName, "_field_number ", protoreflectPackage.Ident("FieldNumber"), " = ", field.Desc.Number()) 307*1c12ee1eSDan Willemsen } 308*1c12ee1eSDan Willemsen g.P(")") 309*1c12ee1eSDan Willemsen g.P() 310*1c12ee1eSDan Willemsen } 311*1c12ee1eSDan Willemsen 312*1c12ee1eSDan Willemsen if len(message.Oneofs) > 0 { 313*1c12ee1eSDan Willemsen g.P("// Oneof names for ", message.Desc.FullName(), ".") 314*1c12ee1eSDan Willemsen g.P("const (") 315*1c12ee1eSDan Willemsen for _, oneof := range message.Oneofs { 316*1c12ee1eSDan Willemsen g.P(message.GoIdent.GoName, "_", oneof.GoName, "_oneof_name ", protoreflectPackage.Ident("Name"), " = ", strconv.Quote(string(oneof.Desc.Name()))) 317*1c12ee1eSDan Willemsen } 318*1c12ee1eSDan Willemsen g.P() 319*1c12ee1eSDan Willemsen for _, oneof := range message.Oneofs { 320*1c12ee1eSDan Willemsen g.P(message.GoIdent.GoName, "_", oneof.GoName, "_oneof_fullname ", protoreflectPackage.Ident("FullName"), " = ", strconv.Quote(string(oneof.Desc.FullName()))) 321*1c12ee1eSDan Willemsen } 322*1c12ee1eSDan Willemsen g.P(")") 323*1c12ee1eSDan Willemsen g.P() 324*1c12ee1eSDan Willemsen } 325*1c12ee1eSDan Willemsen 326*1c12ee1eSDan Willemsen processEnums(message.Enums) 327*1c12ee1eSDan Willemsen processMessages(message.Messages) 328*1c12ee1eSDan Willemsen } 329*1c12ee1eSDan Willemsen } 330*1c12ee1eSDan Willemsen processEnums(file.Enums) 331*1c12ee1eSDan Willemsen processMessages(file.Messages) 332*1c12ee1eSDan Willemsen} 333*1c12ee1eSDan Willemsen 334*1c12ee1eSDan Willemsen// generateSourceContextStringer generates the implementation for the 335*1c12ee1eSDan Willemsen// protoreflect.SourcePath.String method by using information present 336*1c12ee1eSDan Willemsen// in the descriptor.proto. 337*1c12ee1eSDan Willemsenfunc generateSourceContextStringer(gen *protogen.Plugin, file *protogen.File) { 338*1c12ee1eSDan Willemsen if file.Desc.Path() != "google/protobuf/descriptor.proto" { 339*1c12ee1eSDan Willemsen return 340*1c12ee1eSDan Willemsen } 341*1c12ee1eSDan Willemsen 342*1c12ee1eSDan Willemsen importPath := modulePath + "/reflect/protoreflect" 343*1c12ee1eSDan Willemsen g := gen.NewGeneratedFile(importPath+"/source_gen.go", protogen.GoImportPath(importPath)) 344*1c12ee1eSDan Willemsen for _, s := range generatedPreamble { 345*1c12ee1eSDan Willemsen g.P(s) 346*1c12ee1eSDan Willemsen } 347*1c12ee1eSDan Willemsen g.P("package ", path.Base(importPath)) 348*1c12ee1eSDan Willemsen g.P() 349*1c12ee1eSDan Willemsen 350*1c12ee1eSDan Willemsen var messages []*protogen.Message 351*1c12ee1eSDan Willemsen for _, message := range file.Messages { 352*1c12ee1eSDan Willemsen if message.Desc.Name() == "FileDescriptorProto" { 353*1c12ee1eSDan Willemsen messages = append(messages, message) 354*1c12ee1eSDan Willemsen } 355*1c12ee1eSDan Willemsen } 356*1c12ee1eSDan Willemsen seen := make(map[*protogen.Message]bool) 357*1c12ee1eSDan Willemsen 358*1c12ee1eSDan Willemsen for len(messages) > 0 { 359*1c12ee1eSDan Willemsen m := messages[0] 360*1c12ee1eSDan Willemsen messages = messages[1:] 361*1c12ee1eSDan Willemsen if seen[m] { 362*1c12ee1eSDan Willemsen continue 363*1c12ee1eSDan Willemsen } 364*1c12ee1eSDan Willemsen seen[m] = true 365*1c12ee1eSDan Willemsen 366*1c12ee1eSDan Willemsen g.P("func (p *SourcePath) append", m.GoIdent.GoName, "(b []byte) []byte {") 367*1c12ee1eSDan Willemsen g.P("if len(*p) == 0 { return b }") 368*1c12ee1eSDan Willemsen g.P("switch (*p)[0] {") 369*1c12ee1eSDan Willemsen for _, f := range m.Fields { 370*1c12ee1eSDan Willemsen g.P("case ", f.Desc.Number(), ":") 371*1c12ee1eSDan Willemsen var cardinality string 372*1c12ee1eSDan Willemsen switch { 373*1c12ee1eSDan Willemsen case f.Desc.IsMap(): 374*1c12ee1eSDan Willemsen panic("maps are not supported") 375*1c12ee1eSDan Willemsen case f.Desc.IsList(): 376*1c12ee1eSDan Willemsen cardinality = "Repeated" 377*1c12ee1eSDan Willemsen default: 378*1c12ee1eSDan Willemsen cardinality = "Singular" 379*1c12ee1eSDan Willemsen } 380*1c12ee1eSDan Willemsen nextAppender := "nil" 381*1c12ee1eSDan Willemsen if f.Message != nil { 382*1c12ee1eSDan Willemsen nextAppender = "(*SourcePath).append" + f.Message.GoIdent.GoName 383*1c12ee1eSDan Willemsen messages = append(messages, f.Message) 384*1c12ee1eSDan Willemsen } 385*1c12ee1eSDan Willemsen g.P("b = p.append", cardinality, "Field(b, ", strconv.Quote(string(f.Desc.Name())), ", ", nextAppender, ")") 386*1c12ee1eSDan Willemsen } 387*1c12ee1eSDan Willemsen g.P("}") 388*1c12ee1eSDan Willemsen g.P("return b") 389*1c12ee1eSDan Willemsen g.P("}") 390*1c12ee1eSDan Willemsen g.P() 391*1c12ee1eSDan Willemsen } 392*1c12ee1eSDan Willemsen} 393*1c12ee1eSDan Willemsen 394*1c12ee1eSDan Willemsenfunc syncOutput(dstDir, srcDir string) { 395*1c12ee1eSDan Willemsen filepath.Walk(srcDir, func(srcPath string, _ os.FileInfo, _ error) error { 396*1c12ee1eSDan Willemsen if !strings.HasSuffix(srcPath, ".go") && !strings.HasSuffix(srcPath, ".meta") { 397*1c12ee1eSDan Willemsen return nil 398*1c12ee1eSDan Willemsen } 399*1c12ee1eSDan Willemsen relPath, err := filepath.Rel(srcDir, srcPath) 400*1c12ee1eSDan Willemsen check(err) 401*1c12ee1eSDan Willemsen dstPath := filepath.Join(dstDir, relPath) 402*1c12ee1eSDan Willemsen 403*1c12ee1eSDan Willemsen if run { 404*1c12ee1eSDan Willemsen if copyFile(dstPath, srcPath) { 405*1c12ee1eSDan Willemsen fmt.Println("#", relPath) 406*1c12ee1eSDan Willemsen } 407*1c12ee1eSDan Willemsen } else { 408*1c12ee1eSDan Willemsen cmd := exec.Command("diff", dstPath, srcPath, "-N", "-u") 409*1c12ee1eSDan Willemsen cmd.Stdout = os.Stdout 410*1c12ee1eSDan Willemsen cmd.Run() 411*1c12ee1eSDan Willemsen } 412*1c12ee1eSDan Willemsen return nil 413*1c12ee1eSDan Willemsen }) 414*1c12ee1eSDan Willemsen} 415*1c12ee1eSDan Willemsen 416*1c12ee1eSDan Willemsenfunc copyFile(dstPath, srcPath string) (changed bool) { 417*1c12ee1eSDan Willemsen src, err := ioutil.ReadFile(srcPath) 418*1c12ee1eSDan Willemsen check(err) 419*1c12ee1eSDan Willemsen check(os.MkdirAll(filepath.Dir(dstPath), 0775)) 420*1c12ee1eSDan Willemsen dst, _ := ioutil.ReadFile(dstPath) 421*1c12ee1eSDan Willemsen if bytes.Equal(src, dst) { 422*1c12ee1eSDan Willemsen return false 423*1c12ee1eSDan Willemsen } 424*1c12ee1eSDan Willemsen check(ioutil.WriteFile(dstPath, src, 0664)) 425*1c12ee1eSDan Willemsen return true 426*1c12ee1eSDan Willemsen} 427*1c12ee1eSDan Willemsen 428*1c12ee1eSDan Willemsenfunc check(err error) { 429*1c12ee1eSDan Willemsen if err != nil { 430*1c12ee1eSDan Willemsen panic(err) 431*1c12ee1eSDan Willemsen } 432*1c12ee1eSDan Willemsen} 433