Allow wrapping of PackageContext

Turn PackageContext into an interface so that build systems can wrap it
to add more custom helpers.

This does introduce an API change, though it should be fairly simple.
NewPackageContext used to provide an opaque *PackageContext struct, now it
provides a PackageContext interface.

Change-Id: I383c64a303d857ef5e0dec86ad77f791ba4c9639
This commit is contained in:
Dan Willemsen 2015-11-25 15:29:32 -08:00
parent 6afb72ff1b
commit aeffbf776a
7 changed files with 99 additions and 77 deletions

View file

@ -82,7 +82,7 @@ type Context struct {
ignoreUnknownModuleTypes bool
// set during PrepareBuildActions
pkgNames map[*PackageContext]string
pkgNames map[*packageContext]string
globalVariables map[Variable]*ninjaString
globalPools map[Pool]*poolDef
globalRules map[Rule]*ruleDef
@ -1919,13 +1919,13 @@ func (c *Context) setNinjaBuildDir(value *ninjaString) {
}
func (c *Context) makeUniquePackageNames(
liveGlobals *liveTracker) map[*PackageContext]string {
liveGlobals *liveTracker) map[*packageContext]string {
pkgs := make(map[string]*PackageContext)
pkgNames := make(map[*PackageContext]string)
longPkgNames := make(map[*PackageContext]bool)
pkgs := make(map[string]*packageContext)
pkgNames := make(map[*packageContext]string)
longPkgNames := make(map[*packageContext]bool)
processPackage := func(pctx *PackageContext) {
processPackage := func(pctx *packageContext) {
if pctx == nil {
// This is a built-in rule and has no package.
return
@ -1972,7 +1972,7 @@ func (c *Context) makeUniquePackageNames(
}
func (c *Context) checkForVariableReferenceCycles(
variables map[Variable]*ninjaString, pkgNames map[*PackageContext]string) {
variables map[Variable]*ninjaString, pkgNames map[*packageContext]string) {
visited := make(map[Variable]bool) // variables that were already checked
checking := make(map[Variable]bool) // variables actively being checked
@ -2313,11 +2313,11 @@ func (c *Context) writeBuildDir(nw *ninjaWriter) error {
}
type globalEntity interface {
fullName(pkgNames map[*PackageContext]string) string
fullName(pkgNames map[*packageContext]string) string
}
type globalEntitySorter struct {
pkgNames map[*PackageContext]string
pkgNames map[*packageContext]string
entities []globalEntity
}

View file

@ -137,9 +137,9 @@ type ModuleContext interface {
ModuleSubDir() string
Variable(pctx *PackageContext, name, value string)
Rule(pctx *PackageContext, name string, params RuleParams, argNames ...string) Rule
Build(pctx *PackageContext, params BuildParams)
Variable(pctx PackageContext, name, value string)
Rule(pctx PackageContext, name string, params RuleParams, argNames ...string) Rule
Build(pctx PackageContext, params BuildParams)
AddNinjaFileDeps(deps ...string)
@ -267,7 +267,7 @@ func (m *moduleContext) ModuleSubDir() string {
return m.module.variantName
}
func (m *moduleContext) Variable(pctx *PackageContext, name, value string) {
func (m *moduleContext) Variable(pctx PackageContext, name, value string) {
m.scope.ReparentTo(pctx)
v, err := m.scope.AddLocalVariable(name, value)
@ -278,7 +278,7 @@ func (m *moduleContext) Variable(pctx *PackageContext, name, value string) {
m.actionDefs.variables = append(m.actionDefs.variables, v)
}
func (m *moduleContext) Rule(pctx *PackageContext, name string,
func (m *moduleContext) Rule(pctx PackageContext, name string,
params RuleParams, argNames ...string) Rule {
m.scope.ReparentTo(pctx)
@ -293,7 +293,7 @@ func (m *moduleContext) Rule(pctx *PackageContext, name string,
return r
}
func (m *moduleContext) Build(pctx *PackageContext, params BuildParams) {
func (m *moduleContext) Build(pctx PackageContext, params BuildParams) {
m.scope.ReparentTo(pctx)
def, err := parseBuildParams(m.scope, &params)

View file

@ -207,7 +207,7 @@ func parseRuleParams(scope scope, params *RuleParams) (*ruleDef,
}
func (r *ruleDef) WriteTo(nw *ninjaWriter, name string,
pkgNames map[*PackageContext]string) error {
pkgNames map[*packageContext]string) error {
if r.Comment != "" {
err := nw.Comment(r.Comment)
@ -327,7 +327,7 @@ func parseBuildParams(scope scope, params *BuildParams) (*buildDef,
return b, nil
}
func (b *buildDef) WriteTo(nw *ninjaWriter, pkgNames map[*PackageContext]string) error {
func (b *buildDef) WriteTo(nw *ninjaWriter, pkgNames map[*packageContext]string) error {
var (
comment = b.Comment
rule = b.Rule.fullName(pkgNames)
@ -372,7 +372,7 @@ func (b *buildDef) WriteTo(nw *ninjaWriter, pkgNames map[*PackageContext]string)
return nw.BlankLine()
}
func valueList(list []*ninjaString, pkgNames map[*PackageContext]string,
func valueList(list []*ninjaString, pkgNames map[*packageContext]string,
escaper *strings.Replacer) []string {
result := make([]string, len(list))

View file

@ -258,11 +258,11 @@ func parseNinjaStrings(scope scope, strs []string) ([]*ninjaString,
return result, nil
}
func (n *ninjaString) Value(pkgNames map[*PackageContext]string) string {
func (n *ninjaString) Value(pkgNames map[*packageContext]string) string {
return n.ValueWithEscaper(pkgNames, defaultEscaper)
}
func (n *ninjaString) ValueWithEscaper(pkgNames map[*PackageContext]string,
func (n *ninjaString) ValueWithEscaper(pkgNames map[*packageContext]string,
escaper *strings.Replacer) string {
str := escaper.Replace(n.strings[0])

View file

@ -53,20 +53,42 @@ import (
// Outputs: []string{"$myPrivateVar"},
// })
// }
type PackageContext struct {
type PackageContext interface {
Import(pkgPath string)
ImportAs(as, pkgPath string)
StaticVariable(name, value string) Variable
VariableFunc(name string, f func(config interface{}) (string, error)) Variable
VariableConfigMethod(name string, method interface{}) Variable
StaticPool(name string, params PoolParams) Pool
PoolFunc(name string, f func(interface{}) (PoolParams, error)) Pool
StaticRule(name string, params RuleParams, argNames ...string) Rule
RuleFunc(name string, f func(interface{}) (RuleParams, error), argNames ...string) Rule
getScope() *basicScope
}
type packageContext struct {
fullName string
shortName string
pkgPath string
scope *basicScope
}
var _ PackageContext = &packageContext{}
var packageContexts = map[string]*PackageContext{}
func (p *packageContext) getScope() *basicScope {
return p.scope
}
var packageContexts = map[string]*packageContext{}
// NewPackageContext creates a PackageContext object for a given package. The
// pkgPath argument should always be set to the full path used to import the
// package. This function may only be called from a Go package's init()
// function or as part of a package-scoped variable initialization.
func NewPackageContext(pkgPath string) *PackageContext {
func NewPackageContext(pkgPath string) PackageContext {
checkCalledFromInit()
if _, present := packageContexts[pkgPath]; present {
@ -82,7 +104,7 @@ func NewPackageContext(pkgPath string) *PackageContext {
i := strings.LastIndex(pkgPath, "/")
shortName := pkgPath[i+1:]
p := &PackageContext{
p := &packageContext{
fullName: pkgName,
shortName: shortName,
pkgPath: pkgPath,
@ -198,7 +220,7 @@ func pkgPathToName(pkgPath string) string {
// from Go's import declaration, which derives the local name from the package
// clause in the imported package. By convention these names are made to match,
// but this is not required.
func (p *PackageContext) Import(pkgPath string) {
func (p *packageContext) Import(pkgPath string) {
checkCalledFromInit()
importPkg, ok := packageContexts[pkgPath]
if !ok {
@ -214,7 +236,7 @@ func (p *PackageContext) Import(pkgPath string) {
// ImportAs provides the same functionality as Import, but it allows the local
// name that will be used to refer to the package to be specified explicitly.
// It may only be called from a Go package's init() function.
func (p *PackageContext) ImportAs(as, pkgPath string) {
func (p *packageContext) ImportAs(as, pkgPath string) {
checkCalledFromInit()
importPkg, ok := packageContexts[pkgPath]
if !ok {
@ -233,7 +255,7 @@ func (p *PackageContext) ImportAs(as, pkgPath string) {
}
type staticVariable struct {
pctx *PackageContext
pctx *packageContext
name_ string
value_ string
}
@ -247,7 +269,7 @@ type staticVariable struct {
// represents a Ninja variable that will be output. The name argument should
// exactly match the Go variable name, and the value string may reference other
// Ninja variables that are visible within the calling Go package.
func (p *PackageContext) StaticVariable(name, value string) Variable {
func (p *packageContext) StaticVariable(name, value string) Variable {
checkCalledFromInit()
err := validateNinjaName(name)
if err != nil {
@ -263,7 +285,7 @@ func (p *PackageContext) StaticVariable(name, value string) Variable {
return v
}
func (v *staticVariable) packageContext() *PackageContext {
func (v *staticVariable) packageContext() *packageContext {
return v.pctx
}
@ -271,7 +293,7 @@ func (v *staticVariable) name() string {
return v.name_
}
func (v *staticVariable) fullName(pkgNames map[*PackageContext]string) string {
func (v *staticVariable) fullName(pkgNames map[*packageContext]string) string {
return packageNamespacePrefix(pkgNames[v.pctx]) + v.name_
}
@ -289,7 +311,7 @@ func (v *staticVariable) String() string {
}
type variableFunc struct {
pctx *PackageContext
pctx *packageContext
name_ string
value_ func(interface{}) (string, error)
}
@ -305,7 +327,7 @@ type variableFunc struct {
// exactly match the Go variable name, and the value string returned by f may
// reference other Ninja variables that are visible within the calling Go
// package.
func (p *PackageContext) VariableFunc(name string,
func (p *packageContext) VariableFunc(name string,
f func(config interface{}) (string, error)) Variable {
checkCalledFromInit()
@ -335,7 +357,7 @@ func (p *PackageContext) VariableFunc(name string,
// exactly match the Go variable name, and the value string returned by method
// may reference other Ninja variables that are visible within the calling Go
// package.
func (p *PackageContext) VariableConfigMethod(name string,
func (p *packageContext) VariableConfigMethod(name string,
method interface{}) Variable {
checkCalledFromInit()
@ -363,7 +385,7 @@ func (p *PackageContext) VariableConfigMethod(name string,
return v
}
func (v *variableFunc) packageContext() *PackageContext {
func (v *variableFunc) packageContext() *packageContext {
return v.pctx
}
@ -371,7 +393,7 @@ func (v *variableFunc) name() string {
return v.name_
}
func (v *variableFunc) fullName(pkgNames map[*PackageContext]string) string {
func (v *variableFunc) fullName(pkgNames map[*packageContext]string) string {
return packageNamespacePrefix(pkgNames[v.pctx]) + v.name_
}
@ -423,7 +445,7 @@ type argVariable struct {
name_ string
}
func (v *argVariable) packageContext() *PackageContext {
func (v *argVariable) packageContext() *packageContext {
panic("this should not be called")
}
@ -431,7 +453,7 @@ func (v *argVariable) name() string {
return v.name_
}
func (v *argVariable) fullName(pkgNames map[*PackageContext]string) string {
func (v *argVariable) fullName(pkgNames map[*packageContext]string) string {
return v.name_
}
@ -444,7 +466,7 @@ func (v *argVariable) String() string {
}
type staticPool struct {
pctx *PackageContext
pctx *packageContext
name_ string
params PoolParams
}
@ -458,7 +480,7 @@ type staticPool struct {
// represents a Ninja pool that will be output. The name argument should
// exactly match the Go variable name, and the params fields may reference other
// Ninja variables that are visible within the calling Go package.
func (p *PackageContext) StaticPool(name string, params PoolParams) Pool {
func (p *packageContext) StaticPool(name string, params PoolParams) Pool {
checkCalledFromInit()
err := validateNinjaName(name)
@ -475,7 +497,7 @@ func (p *PackageContext) StaticPool(name string, params PoolParams) Pool {
return pool
}
func (p *staticPool) packageContext() *PackageContext {
func (p *staticPool) packageContext() *packageContext {
return p.pctx
}
@ -483,7 +505,7 @@ func (p *staticPool) name() string {
return p.name_
}
func (p *staticPool) fullName(pkgNames map[*PackageContext]string) string {
func (p *staticPool) fullName(pkgNames map[*packageContext]string) string {
return packageNamespacePrefix(pkgNames[p.pctx]) + p.name_
}
@ -500,7 +522,7 @@ func (p *staticPool) String() string {
}
type poolFunc struct {
pctx *PackageContext
pctx *packageContext
name_ string
paramsFunc func(interface{}) (PoolParams, error)
}
@ -515,7 +537,7 @@ type poolFunc struct {
// exactly match the Go variable name, and the string fields of the PoolParams
// returned by f may reference other Ninja variables that are visible within the
// calling Go package.
func (p *PackageContext) PoolFunc(name string, f func(interface{}) (PoolParams,
func (p *packageContext) PoolFunc(name string, f func(interface{}) (PoolParams,
error)) Pool {
checkCalledFromInit()
@ -534,7 +556,7 @@ func (p *PackageContext) PoolFunc(name string, f func(interface{}) (PoolParams,
return pool
}
func (p *poolFunc) packageContext() *PackageContext {
func (p *poolFunc) packageContext() *packageContext {
return p.pctx
}
@ -542,7 +564,7 @@ func (p *poolFunc) name() string {
return p.name_
}
func (p *poolFunc) fullName(pkgNames map[*PackageContext]string) string {
func (p *poolFunc) fullName(pkgNames map[*packageContext]string) string {
return packageNamespacePrefix(pkgNames[p.pctx]) + p.name_
}
@ -566,7 +588,7 @@ type builtinPool struct {
name_ string
}
func (p *builtinPool) packageContext() *PackageContext {
func (p *builtinPool) packageContext() *packageContext {
return nil
}
@ -574,7 +596,7 @@ func (p *builtinPool) name() string {
return p.name_
}
func (p *builtinPool) fullName(pkgNames map[*PackageContext]string) string {
func (p *builtinPool) fullName(pkgNames map[*packageContext]string) string {
return p.name_
}
@ -587,7 +609,7 @@ func (p *builtinPool) String() string {
}
type staticRule struct {
pctx *PackageContext
pctx *packageContext
name_ string
params RuleParams
argNames map[string]bool
@ -613,7 +635,7 @@ type staticRule struct {
// results in the package-scoped variable's value being used for build
// statements that do not override the argument. For argument names that do not
// shadow package-scoped variables the default value is an empty string.
func (p *PackageContext) StaticRule(name string, params RuleParams,
func (p *packageContext) StaticRule(name string, params RuleParams,
argNames ...string) Rule {
checkCalledFromInit()
@ -650,7 +672,7 @@ func (p *PackageContext) StaticRule(name string, params RuleParams,
return r
}
func (r *staticRule) packageContext() *PackageContext {
func (r *staticRule) packageContext() *packageContext {
return r.pctx
}
@ -658,7 +680,7 @@ func (r *staticRule) name() string {
return r.name_
}
func (r *staticRule) fullName(pkgNames map[*PackageContext]string) string {
func (r *staticRule) fullName(pkgNames map[*packageContext]string) string {
return packageNamespacePrefix(pkgNames[r.pctx]) + r.name_
}
@ -692,7 +714,7 @@ func (r *staticRule) String() string {
}
type ruleFunc struct {
pctx *PackageContext
pctx *packageContext
name_ string
paramsFunc func(interface{}) (RuleParams, error)
argNames map[string]bool
@ -719,7 +741,7 @@ type ruleFunc struct {
// scoped variable results in the package-scoped variable's value being used for
// build statements that do not override the argument. For argument names that
// do not shadow package-scoped variables the default value is an empty string.
func (p *PackageContext) RuleFunc(name string, f func(interface{}) (RuleParams,
func (p *packageContext) RuleFunc(name string, f func(interface{}) (RuleParams,
error), argNames ...string) Rule {
checkCalledFromInit()
@ -756,7 +778,7 @@ func (p *PackageContext) RuleFunc(name string, f func(interface{}) (RuleParams,
return rule
}
func (r *ruleFunc) packageContext() *PackageContext {
func (r *ruleFunc) packageContext() *packageContext {
return r.pctx
}
@ -764,7 +786,7 @@ func (r *ruleFunc) name() string {
return r.name_
}
func (r *ruleFunc) fullName(pkgNames map[*PackageContext]string) string {
func (r *ruleFunc) fullName(pkgNames map[*packageContext]string) string {
return packageNamespacePrefix(pkgNames[r.pctx]) + r.name_
}
@ -807,7 +829,7 @@ type builtinRule struct {
sync.Mutex // protects scope_ during lazy creation
}
func (r *builtinRule) packageContext() *PackageContext {
func (r *builtinRule) packageContext() *packageContext {
return nil
}
@ -815,7 +837,7 @@ func (r *builtinRule) name() string {
return r.name_
}
func (r *builtinRule) fullName(pkgNames map[*PackageContext]string) string {
func (r *builtinRule) fullName(pkgNames map[*packageContext]string) string {
return r.name_
}

View file

@ -25,9 +25,9 @@ import (
// to the output .ninja file. A variable may contain references to other global
// Ninja variables, but circular variable references are not allowed.
type Variable interface {
packageContext() *PackageContext
packageContext() *packageContext
name() string // "foo"
fullName(pkgNames map[*PackageContext]string) string // "pkg.foo" or "path.to.pkg.foo"
fullName(pkgNames map[*packageContext]string) string // "pkg.foo" or "path.to.pkg.foo"
value(config interface{}) (*ninjaString, error)
String() string
}
@ -35,9 +35,9 @@ type Variable interface {
// A Pool represents a Ninja pool that will be written to the output .ninja
// file.
type Pool interface {
packageContext() *PackageContext
packageContext() *packageContext
name() string // "foo"
fullName(pkgNames map[*PackageContext]string) string // "pkg.foo" or "path.to.pkg.foo"
fullName(pkgNames map[*packageContext]string) string // "pkg.foo" or "path.to.pkg.foo"
def(config interface{}) (*poolDef, error)
String() string
}
@ -45,9 +45,9 @@ type Pool interface {
// A Rule represents a Ninja build rule that will be written to the output
// .ninja file.
type Rule interface {
packageContext() *PackageContext
packageContext() *packageContext
name() string // "foo"
fullName(pkgNames map[*PackageContext]string) string // "pkg.foo" or "path.to.pkg.foo"
fullName(pkgNames map[*packageContext]string) string // "pkg.foo" or "path.to.pkg.foo"
def(config interface{}) (*ruleDef, error)
scope() *basicScope
isArg(argName string) bool
@ -260,8 +260,8 @@ func newLocalScope(parent *basicScope, namePrefix string) *localScope {
// package context. This allows a ModuleContext and SingletonContext to call
// a function defined in a different Go package and have that function retain
// access to all of the package-scoped variables of its own package.
func (s *localScope) ReparentTo(pctx *PackageContext) {
s.scope.parent = pctx.scope
func (s *localScope) ReparentTo(pctx PackageContext) {
s.scope.parent = pctx.getScope()
}
func (s *localScope) LookupVariable(name string) (Variable, error) {
@ -354,7 +354,7 @@ type localVariable struct {
value_ *ninjaString
}
func (l *localVariable) packageContext() *PackageContext {
func (l *localVariable) packageContext() *packageContext {
return nil
}
@ -362,7 +362,7 @@ func (l *localVariable) name() string {
return l.name_
}
func (l *localVariable) fullName(pkgNames map[*PackageContext]string) string {
func (l *localVariable) fullName(pkgNames map[*packageContext]string) string {
return l.namePrefix + l.name_
}
@ -382,7 +382,7 @@ type localRule struct {
scope_ *basicScope
}
func (l *localRule) packageContext() *PackageContext {
func (l *localRule) packageContext() *packageContext {
return nil
}
@ -390,7 +390,7 @@ func (l *localRule) name() string {
return l.name_
}
func (l *localRule) fullName(pkgNames map[*PackageContext]string) string {
func (l *localRule) fullName(pkgNames map[*packageContext]string) string {
return l.namePrefix + l.name_
}

View file

@ -32,15 +32,15 @@ type SingletonContext interface {
ModuleErrorf(module Module, format string, args ...interface{})
Errorf(format string, args ...interface{})
Variable(pctx *PackageContext, name, value string)
Rule(pctx *PackageContext, name string, params RuleParams, argNames ...string) Rule
Build(pctx *PackageContext, params BuildParams)
Variable(pctx PackageContext, name, value string)
Rule(pctx PackageContext, name string, params RuleParams, argNames ...string) Rule
Build(pctx PackageContext, params BuildParams)
RequireNinjaVersion(major, minor, micro int)
// SetNinjaBuildDir sets the value of the top-level "builddir" Ninja variable
// that controls where Ninja stores its build log files. This value can be
// set at most one time for a single build, later calls are ignored.
SetNinjaBuildDir(pctx *PackageContext, value string)
SetNinjaBuildDir(pctx PackageContext, value string)
VisitAllModules(visit func(Module))
VisitAllModulesIf(pred func(Module) bool, visit func(Module))
@ -96,7 +96,7 @@ func (s *singletonContext) Errorf(format string, args ...interface{}) {
s.errs = append(s.errs, fmt.Errorf(format, args...))
}
func (s *singletonContext) Variable(pctx *PackageContext, name, value string) {
func (s *singletonContext) Variable(pctx PackageContext, name, value string) {
s.scope.ReparentTo(pctx)
v, err := s.scope.AddLocalVariable(name, value)
@ -107,7 +107,7 @@ func (s *singletonContext) Variable(pctx *PackageContext, name, value string) {
s.actionDefs.variables = append(s.actionDefs.variables, v)
}
func (s *singletonContext) Rule(pctx *PackageContext, name string,
func (s *singletonContext) Rule(pctx PackageContext, name string,
params RuleParams, argNames ...string) Rule {
s.scope.ReparentTo(pctx)
@ -122,7 +122,7 @@ func (s *singletonContext) Rule(pctx *PackageContext, name string,
return r
}
func (s *singletonContext) Build(pctx *PackageContext, params BuildParams) {
func (s *singletonContext) Build(pctx PackageContext, params BuildParams) {
s.scope.ReparentTo(pctx)
def, err := parseBuildParams(s.scope, &params)
@ -137,7 +137,7 @@ func (s *singletonContext) RequireNinjaVersion(major, minor, micro int) {
s.context.requireNinjaVersion(major, minor, micro)
}
func (s *singletonContext) SetNinjaBuildDir(pctx *PackageContext, value string) {
func (s *singletonContext) SetNinjaBuildDir(pctx PackageContext, value string) {
s.scope.ReparentTo(pctx)
ninjaValue, err := parseNinjaString(s.scope, value)