func (p protobufLocator) GoTypeForName(name types.Name) *types.Type { if len(name.Package) == 0 { name.Package = p.localGoPackage } return p.universe.Type(name) }
func Run(g *Generator) { if g.Common.VerifyOnly { g.OnlyIDL = true g.Clean = false } b := parser.New() b.AddBuildTags("proto") omitTypes := map[types.Name]struct{}{} for _, t := range strings.Split(g.DropEmbeddedFields, ",") { name := types.Name{} if i := strings.LastIndex(t, "."); i != -1 { name.Package, name.Name = t[:i], t[i+1:] } else { name.Name = t } if len(name.Name) == 0 { log.Fatalf("--drop-embedded-types requires names in the form of [GOPACKAGE.]TYPENAME: %v", t) } omitTypes[name] = struct{}{} } boilerplate, err := g.Common.LoadGoBoilerplate() if err != nil { log.Fatalf("Failed loading boilerplate: %v", err) } protobufNames := NewProtobufNamer() outputPackages := generator.Packages{} for _, d := range strings.Split(g.Packages, ",") { generateAllTypes, outputPackage := true, true switch { case strings.HasPrefix(d, "+"): d = d[1:] generateAllTypes = false case strings.HasPrefix(d, "-"): d = d[1:] outputPackage = false } name := protoSafePackage(d) parts := strings.SplitN(d, "=", 2) if len(parts) > 1 { d = parts[0] name = parts[1] } p := newProtobufPackage(d, name, generateAllTypes, omitTypes) header := append([]byte{}, boilerplate...) header = append(header, p.HeaderText...) p.HeaderText = header protobufNames.Add(p) if outputPackage { outputPackages = append(outputPackages, p) } } if !g.Common.VerifyOnly { for _, p := range outputPackages { if err := p.(*protobufPackage).Clean(g.OutputBase); err != nil { log.Fatalf("Unable to clean package %s: %v", p.Name(), err) } } } if g.Clean { return } for _, p := range protobufNames.List() { if err := b.AddDir(p.Path()); err != nil { log.Fatalf("Unable to add directory %q: %v", p.Path(), err) } } c, err := generator.NewContext( b, namer.NameSystems{ "public": namer.NewPublicNamer(3), "proto": protobufNames, }, "public", ) if err != nil { log.Fatalf("Failed making a context: %v", err) } c.Verify = g.Common.VerifyOnly c.FileTypes["protoidl"] = NewProtoFile() if err := protobufNames.AssignTypesToPackages(c); err != nil { log.Fatalf("Failed to identify Common types: %v", err) } if err := c.ExecutePackages(g.OutputBase, outputPackages); err != nil { log.Fatalf("Failed executing generator: %v", err) } if g.OnlyIDL { return } if _, err := exec.LookPath("protoc"); err != nil { log.Fatalf("Unable to find 'protoc': %v", err) } searchArgs := []string{"-I", ".", "-I", g.OutputBase} if len(g.ProtoImport) != 0 { for _, s := range g.ProtoImport { searchArgs = append(searchArgs, "-I", s) } } args := append(searchArgs, fmt.Sprintf("--gogo_out=%s", g.OutputBase)) buf := &bytes.Buffer{} if len(g.Conditional) > 0 { fmt.Fprintf(buf, "// +build %s\n\n", g.Conditional) } buf.Write(boilerplate) for _, outputPackage := range outputPackages { p := outputPackage.(*protobufPackage) path := filepath.Join(g.OutputBase, p.ImportPath()) outputPath := filepath.Join(g.OutputBase, p.OutputPath()) // generate the gogoprotobuf protoc cmd := exec.Command("protoc", append(args, path)...) out, err := cmd.CombinedOutput() if len(out) > 0 { log.Printf(string(out)) } if err != nil { log.Println(strings.Join(cmd.Args, " ")) log.Fatalf("Unable to generate protoc on %s: %v", p.PackageName, err) } if g.SkipGeneratedRewrite { continue } // alter the generated protobuf file to remove the generated types (but leave the serializers) and rewrite the // package statement to match the desired package name if err := RewriteGeneratedGogoProtobufFile(outputPath, p.ExtractGeneratedType, p.OptionalTypeName, buf.Bytes()); err != nil { log.Fatalf("Unable to rewrite generated %s: %v", outputPath, err) } // sort imports cmd = exec.Command("goimports", "-w", outputPath) out, err = cmd.CombinedOutput() if len(out) > 0 { log.Printf(string(out)) } if err != nil { log.Println(strings.Join(cmd.Args, " ")) log.Fatalf("Unable to rewrite imports for %s: %v", p.PackageName, err) } // format and simplify the generated file cmd = exec.Command("gofmt", "-s", "-w", outputPath) out, err = cmd.CombinedOutput() if len(out) > 0 { log.Printf(string(out)) } if err != nil { log.Println(strings.Join(cmd.Args, " ")) log.Fatalf("Unable to apply gofmt for %s: %v", p.PackageName, err) } } if g.SkipGeneratedRewrite { return } if !g.KeepGogoproto { // generate, but do so without gogoprotobuf extensions for _, outputPackage := range outputPackages { p := outputPackage.(*protobufPackage) p.OmitGogo = true } if err := c.ExecutePackages(g.OutputBase, outputPackages); err != nil { log.Fatalf("Failed executing generator: %v", err) } } for _, outputPackage := range outputPackages { p := outputPackage.(*protobufPackage) if len(p.StructTags) == 0 { continue } pattern := filepath.Join(g.OutputBase, p.PackagePath, "*.go") files, err := filepath.Glob(pattern) if err != nil { log.Fatalf("Can't glob pattern %q: %v", pattern, err) } for _, s := range files { if strings.HasSuffix(s, "_test.go") { continue } if err := RewriteTypesWithProtobufStructTags(s, p.StructTags); err != nil { log.Fatalf("Unable to rewrite with struct tags %s: %v", s, err) } } } }
// CastTypeName returns the cast type name of a Go type // TODO: delegate to a new localgo namer? func (p protobufLocator) CastTypeName(name types.Name) string { if name.Package == p.localGoPackage { return name.Name } return name.String() }