func construct(t *testing.T, files map[string]string, testNamer namer.Namer) (*parser.Builder, types.Universe, []*types.Type) { b := parser.New() for name, src := range files { if err := b.AddFile(filepath.Dir(name), name, []byte(src)); err != nil { t.Fatal(err) } } u, err := b.FindTypes() if err != nil { t.Fatal(err) } orderer := namer.Orderer{Namer: testNamer} o := orderer.OrderUniverse(u) return b, u, o }
// NewBuilder makes a new parser.Builder and populates it with the input // directories. func (g *GeneratorArgs) NewBuilder() (*parser.Builder, error) { b := parser.New() // Ignore all auto-generated files. b.AddBuildTags(g.GeneratedBuildTag) for _, d := range g.InputDirs { var err error if strings.HasSuffix(d, "/...") { err = b.AddDirRecursive(strings.TrimSuffix(d, "/...")) } else { err = b.AddDir(d) } if err != nil { return nil, fmt.Errorf("unable to add directory %q: %v", d, err) } } return b, nil }
func getPrioritySignatures() ([]*types.Signature, error) { filePath := "./../types.go" pkgName := filepath.Dir(filePath) builder := parser.New() if err := builder.AddDir(pkgName); err != nil { return nil, err } universe, err := builder.FindTypes() if err != nil { return nil, err } signatures := []string{"PriorityFunction", "PriorityMapFunction", "PriorityReduceFunction"} results := make([]*types.Signature, 0, len(signatures)) for _, signature := range signatures { result, ok := universe[pkgName].Types[signature] if !ok { return nil, fmt.Errorf("%s type not defined", signature) } results = append(results, result.Signature) } return results, nil }
// GetPublicFunctions lists all public functions (not methods) from a golang source file. func GetPublicFunctions(pkg, filePath string) ([]*types.Type, error) { builder := go2idlparser.New() data, err := ioutil.ReadFile(filePath) if err != nil { return nil, err } if err := builder.AddFile(pkg, filePath, data); err != nil { return nil, err } universe, err := builder.FindTypes() if err != nil { return nil, err } var functions []*types.Type // Create the AST by parsing src. fset := token.NewFileSet() // positions are relative to fset f, err := parser.ParseFile(fset, filePath, nil, 0) if err != nil { return nil, fmt.Errorf("failed parse file to list functions: %v", err) } // Inspect the AST and print all identifiers and literals. ast.Inspect(f, func(n ast.Node) bool { var s string switch x := n.(type) { case *ast.FuncDecl: s = x.Name.Name // It's a function (not method), and is public, record it. if x.Recv == nil && isPublic(s) { functions = append(functions, universe[pkg].Function(x.Name.Name)) } } return true }) return functions, nil }
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) } } } }