func()

in generator/execute.go [215:313]


func (c *Context) ExecutePackage(outDir string, p Package) error {
	path := filepath.Join(outDir, p.Path())

	// When working outside of GOPATH, we typically won't want to generate the
	// full path for a package. For example, if our current project's root/base
	// package is github.com/foo/bar, outDir=., p.Path()=github.com/foo/bar/generated,
	// then we really want to be writing files to ./generated, not ./github.com/foo/bar/generated.
	// The following will trim a path prefix (github.com/foo/bar) from p.Path() to arrive at
	// a relative path that works with projects not in GOPATH.
	if c.TrimPathPrefix != "" {
		separator := string(filepath.Separator)
		if !strings.HasSuffix(c.TrimPathPrefix, separator) {
			c.TrimPathPrefix += separator
		}

		path = strings.TrimPrefix(path, c.TrimPathPrefix)
	}
	klog.V(5).Infof("Processing package %q, disk location %q", p.Name(), path)
	// Filter out any types the *package* doesn't care about.
	packageContext := c.filteredBy(p.Filter)
	os.MkdirAll(path, 0755)
	files := map[string]*File{}
	for _, g := range p.Generators(packageContext) {
		// Filter out types the *generator* doesn't care about.
		genContext := packageContext.filteredBy(g.Filter)
		// Now add any extra name systems defined by this generator
		genContext = genContext.addNameSystems(g.Namers(genContext))

		fileType := g.FileType()
		if len(fileType) == 0 {
			return fmt.Errorf("generator %q must specify a file type", g.Name())
		}
		f := files[g.Filename()]
		if f == nil {
			// This is the first generator to reference this file, so start it.
			f = &File{
				Name:              g.Filename(),
				FileType:          fileType,
				PackageName:       p.Name(),
				PackagePath:       p.Path(),
				PackageSourcePath: p.SourcePath(),
				Header:            p.Header(g.Filename()),
				Imports:           map[string]struct{}{},
			}
			files[f.Name] = f
		} else {
			if f.FileType != g.FileType() {
				return fmt.Errorf("file %q already has type %q, but generator %q wants to use type %q", f.Name, f.FileType, g.Name(), g.FileType())
			}
		}

		if vars := g.PackageVars(genContext); len(vars) > 0 {
			addIndentHeaderComment(&f.Vars, "Package-wide variables from generator %q.", g.Name())
			for _, v := range vars {
				if _, err := fmt.Fprintf(&f.Vars, "%s\n", v); err != nil {
					return err
				}
			}
		}
		if consts := g.PackageConsts(genContext); len(consts) > 0 {
			addIndentHeaderComment(&f.Consts, "Package-wide consts from generator %q.", g.Name())
			for _, v := range consts {
				if _, err := fmt.Fprintf(&f.Consts, "%s\n", v); err != nil {
					return err
				}
			}
		}
		if err := genContext.executeBody(&f.Body, g); err != nil {
			return err
		}
		if imports := g.Imports(genContext); len(imports) > 0 {
			for _, i := range imports {
				f.Imports[i] = struct{}{}
			}
		}
	}

	var errors []error
	for _, f := range files {
		finalPath := filepath.Join(path, f.Name)
		assembler, ok := c.FileTypes[f.FileType]
		if !ok {
			return fmt.Errorf("the file type %q registered for file %q does not exist in the context", f.FileType, f.Name)
		}
		var err error
		if c.Verify {
			err = assembler.VerifyFile(f, finalPath)
		} else {
			err = assembler.AssembleFile(f, finalPath)
		}
		if err != nil {
			errors = append(errors, err)
		}
	}
	if len(errors) > 0 {
		return fmt.Errorf("errors in package %q:\n%v\n", p.Path(), strings.Join(errs2strings(errors), "\n"))
	}
	return nil
}