2017-02-12 04:59:33 +00:00
|
|
|
// Package gen takes the Chrome protocol domain definitions and applies the
|
|
|
|
// necessary code generation templates.
|
2017-01-24 15:09:23 +00:00
|
|
|
package gen
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"path"
|
|
|
|
|
|
|
|
"github.com/gedex/inflector"
|
|
|
|
qtpl "github.com/valyala/quicktemplate"
|
|
|
|
|
2017-01-26 07:28:34 +00:00
|
|
|
"github.com/knq/chromedp/cmd/chromedp-gen/internal"
|
|
|
|
"github.com/knq/chromedp/cmd/chromedp-gen/templates"
|
2017-01-24 15:09:23 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// fileBuffers is a type to manage buffers for file data.
|
|
|
|
type fileBuffers map[string]*bytes.Buffer
|
|
|
|
|
|
|
|
// GenerateDomains generates domains for the Chrome Debugging Protocol domain
|
2017-02-12 04:59:33 +00:00
|
|
|
// definitions, returning a set of file buffers as a map of the file name ->
|
|
|
|
// content.
|
2017-01-26 07:28:34 +00:00
|
|
|
func GenerateDomains(domains []*internal.Domain) map[string]*bytes.Buffer {
|
2017-01-24 15:09:23 +00:00
|
|
|
fb := make(fileBuffers)
|
|
|
|
|
|
|
|
var w *qtpl.Writer
|
|
|
|
|
|
|
|
// determine base (also used for the domains manager type name)
|
2017-01-26 07:28:34 +00:00
|
|
|
pkgBase := path.Base(*internal.FlagPkg)
|
|
|
|
internal.DomainTypeSuffix = inflector.Singularize(internal.ForceCamel(pkgBase))
|
2017-01-24 15:09:23 +00:00
|
|
|
|
|
|
|
// generate internal types
|
2017-01-26 07:28:34 +00:00
|
|
|
fb.generateCDPTypes(domains)
|
2017-01-24 15:09:23 +00:00
|
|
|
|
|
|
|
// generate util package
|
|
|
|
fb.generateUtilPackage(domains)
|
|
|
|
|
|
|
|
// do individual domain templates
|
|
|
|
for _, d := range domains {
|
|
|
|
pkgName := d.PackageName()
|
|
|
|
pkgOut := pkgName + "/" + pkgName + ".go"
|
|
|
|
|
|
|
|
// do command template
|
|
|
|
w = fb.get(pkgOut, pkgName, d)
|
2017-01-26 07:28:34 +00:00
|
|
|
templates.StreamDomainTemplate(w, d, domains)
|
2017-01-24 15:09:23 +00:00
|
|
|
fb.release(w)
|
|
|
|
|
|
|
|
// generate domain types
|
|
|
|
if len(d.Types) != 0 {
|
|
|
|
fb.generateTypes(
|
|
|
|
pkgName+"/types.go",
|
2017-01-26 07:28:34 +00:00
|
|
|
d.Types, internal.TypePrefix, internal.TypeSuffix, d, domains,
|
2017-01-24 15:09:23 +00:00
|
|
|
"", "", "", "", "",
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// generate domain event types
|
|
|
|
if len(d.Events) != 0 {
|
|
|
|
fb.generateTypes(
|
|
|
|
pkgName+"/events.go",
|
2017-01-26 07:28:34 +00:00
|
|
|
d.Events, internal.EventTypePrefix, internal.EventTypeSuffix, d, domains,
|
|
|
|
"EventTypes", "cdp.MethodType", "cdp."+internal.EventMethodPrefix+d.String(), internal.EventMethodSuffix,
|
|
|
|
"All event types in the domain.",
|
2017-01-24 15:09:23 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return map[string]*bytes.Buffer(fb)
|
|
|
|
}
|
|
|
|
|
2017-01-26 07:28:34 +00:00
|
|
|
// generateCDPTypes generates the internal types for domain d.
|
2017-01-24 15:09:23 +00:00
|
|
|
//
|
2017-02-12 04:59:33 +00:00
|
|
|
// Because there are circular package dependencies, some types need to be moved
|
|
|
|
// to eliminate the circular dependencies. Please see the fixup package for a
|
|
|
|
// list of the "internal" CDP types.
|
2017-01-26 07:28:34 +00:00
|
|
|
func (fb fileBuffers) generateCDPTypes(domains []*internal.Domain) {
|
|
|
|
var types []*internal.Type
|
2017-01-24 15:09:23 +00:00
|
|
|
for _, d := range domains {
|
|
|
|
// process internal types
|
|
|
|
for _, t := range d.Types {
|
2017-02-12 04:59:33 +00:00
|
|
|
if internal.IsCDPType(d.Domain, t.IDorName()) {
|
2017-01-26 07:28:34 +00:00
|
|
|
types = append(types, t)
|
2017-01-24 15:09:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-26 07:28:34 +00:00
|
|
|
pkg := path.Base(*internal.FlagPkg)
|
|
|
|
cdpDomain := &internal.Domain{
|
|
|
|
Domain: internal.DomainType("cdp"),
|
|
|
|
Types: types,
|
|
|
|
}
|
|
|
|
doms := append(domains, cdpDomain)
|
|
|
|
|
|
|
|
w := fb.get(pkg+".go", pkg, nil)
|
|
|
|
for _, t := range types {
|
|
|
|
templates.StreamTypeTemplate(w, t, internal.TypePrefix, internal.TypeSuffix, cdpDomain, doms, nil, false, false)
|
|
|
|
}
|
2017-01-24 15:09:23 +00:00
|
|
|
fb.release(w)
|
|
|
|
}
|
|
|
|
|
|
|
|
// generateUtilPackage generates the util package.
|
|
|
|
//
|
2017-02-12 04:59:33 +00:00
|
|
|
// Currently only contains the low-level message unmarshaler -- if this wasn't
|
|
|
|
// in a separate package, then there would be circular dependencies.
|
2017-01-26 07:28:34 +00:00
|
|
|
func (fb fileBuffers) generateUtilPackage(domains []*internal.Domain) {
|
2017-02-12 04:59:33 +00:00
|
|
|
// generate import map data
|
2017-01-24 15:09:23 +00:00
|
|
|
importMap := map[string]string{
|
2017-01-26 07:28:34 +00:00
|
|
|
*internal.FlagPkg: "cdp",
|
2017-01-24 15:09:23 +00:00
|
|
|
}
|
|
|
|
for _, d := range domains {
|
2017-01-26 07:28:34 +00:00
|
|
|
importMap[*internal.FlagPkg+"/"+d.PackageName()] = d.PackageImportAlias()
|
2017-01-24 15:09:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
w := fb.get("util/util.go", "util", nil)
|
2017-01-26 07:28:34 +00:00
|
|
|
templates.StreamFileImportTemplate(w, importMap)
|
|
|
|
templates.StreamExtraUtilTemplate(w, domains)
|
2017-01-24 15:09:23 +00:00
|
|
|
fb.release(w)
|
|
|
|
}
|
|
|
|
|
2017-02-12 04:59:33 +00:00
|
|
|
// generateTypes generates the types for a domain.
|
2017-01-24 15:09:23 +00:00
|
|
|
func (fb fileBuffers) generateTypes(
|
|
|
|
path string,
|
2017-01-26 07:28:34 +00:00
|
|
|
types []*internal.Type, prefix, suffix string, d *internal.Domain, domains []*internal.Domain,
|
2017-01-24 15:09:23 +00:00
|
|
|
emit, emitType, emitPrefix, emitSuffix, emitDesc string,
|
|
|
|
) {
|
|
|
|
w := fb.get(path, d.PackageName(), d)
|
|
|
|
|
|
|
|
// add internal import
|
2017-01-26 07:28:34 +00:00
|
|
|
templates.StreamFileImportTemplate(w, map[string]string{*internal.FlagPkg: "cdp"})
|
2017-01-24 15:09:23 +00:00
|
|
|
|
|
|
|
// process type list
|
|
|
|
var names []string
|
|
|
|
for _, t := range types {
|
2017-02-12 04:59:33 +00:00
|
|
|
if internal.IsCDPType(d.Domain, t.IDorName()) {
|
2017-01-24 15:09:23 +00:00
|
|
|
continue
|
|
|
|
}
|
2017-01-26 07:28:34 +00:00
|
|
|
templates.StreamTypeTemplate(w, t, prefix, suffix, d, domains, nil, false, false)
|
2017-01-24 15:09:23 +00:00
|
|
|
names = append(names, t.TypeName(emitPrefix, emitSuffix))
|
|
|
|
}
|
|
|
|
|
|
|
|
// emit var
|
|
|
|
if emit != "" {
|
|
|
|
s := "[]" + emitType + "{"
|
|
|
|
for _, n := range names {
|
|
|
|
s += "\n" + n + ","
|
|
|
|
}
|
|
|
|
s += "\n}"
|
2017-01-26 07:28:34 +00:00
|
|
|
templates.StreamFileVarTemplate(w, emit, s, emitDesc)
|
2017-01-24 15:09:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fb.release(w)
|
|
|
|
}
|
|
|
|
|
|
|
|
// get retrieves the file buffer for s, or creates it if it is not yet available.
|
2017-01-26 07:28:34 +00:00
|
|
|
func (fb fileBuffers) get(s string, pkgName string, d *internal.Domain) *qtpl.Writer {
|
2017-01-24 15:09:23 +00:00
|
|
|
// check if it already exists
|
|
|
|
if b, ok := fb[s]; ok {
|
|
|
|
return qtpl.AcquireWriter(b)
|
|
|
|
}
|
|
|
|
|
|
|
|
// create buffer
|
|
|
|
b := new(bytes.Buffer)
|
|
|
|
fb[s] = b
|
|
|
|
w := qtpl.AcquireWriter(b)
|
|
|
|
|
|
|
|
v := d
|
|
|
|
if b := path.Base(s); b != pkgName+".go" {
|
|
|
|
v = nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// add package header
|
2017-01-26 07:28:34 +00:00
|
|
|
templates.StreamFileHeader(w, pkgName, v)
|
2017-01-24 15:09:23 +00:00
|
|
|
|
|
|
|
return w
|
|
|
|
}
|
|
|
|
|
|
|
|
// release releases a template writer.
|
|
|
|
func (fb fileBuffers) release(w *qtpl.Writer) {
|
|
|
|
qtpl.ReleaseWriter(w)
|
|
|
|
}
|