Reimplement VisitDirectDeps[If] in on Context.walkdeps

VisitDirectDeps[If] need to know the parent in order to support
OtherModuleDependencyTag(), remove Context.visitDirectDeps[If] and
reimplement [Module]Context.VisitDirectDeps[If] using Context.walkdeps.

Change-Id: I2faac2d100d2a0ad2a4f1d8250997eed1a7ef6f0
Test: TestVisit
This commit is contained in:
Colin Cross 2016-08-06 22:52:01 -07:00
parent 365bc6b3ea
commit bafd5f5a2b
4 changed files with 128 additions and 92 deletions

View file

@ -1993,15 +1993,15 @@ func (c *Context) processLocalBuildActions(out, in *localBuildActions,
}
func (c *Context) walkDeps(topModule *moduleInfo,
visit func(Module, Module) bool) {
visitDown func(depInfo, *moduleInfo) bool, visitUp func(depInfo, *moduleInfo)) {
visited := make(map[*moduleInfo]bool)
var visiting *moduleInfo
defer func() {
if r := recover(); r != nil {
panic(newPanicErrorf(r, "WalkDeps(%s, %s) for dependency %s",
topModule, funcName(visit), visiting))
panic(newPanicErrorf(r, "WalkDeps(%s, %s, %s) for dependency %s",
topModule, funcName(visitDown), funcName(visitUp), visiting))
}
}()
@ -2011,9 +2011,16 @@ func (c *Context) walkDeps(topModule *moduleInfo,
if !visited[dep.module] {
visited[dep.module] = true
visiting = dep.module
if visit(dep.module.logicModule, module.logicModule) {
recurse := true
if visitDown != nil {
recurse = visitDown(dep, module)
}
if recurse {
walk(dep.module)
}
if visitUp != nil {
visitUp(dep, module)
}
}
}
}
@ -2023,68 +2030,6 @@ func (c *Context) walkDeps(topModule *moduleInfo,
type innerPanicError error
func (c *Context) visitDepsDepthFirst(topModule *moduleInfo, visit func(Module)) {
visited := make(map[*moduleInfo]bool)
var visiting *moduleInfo
defer func() {
if r := recover(); r != nil {
panic(newPanicErrorf(r, "VisitDepsDepthFirst(%s, %s) for dependency %s",
topModule, funcName(visit), visiting))
}
}()
var walk func(module *moduleInfo)
walk = func(module *moduleInfo) {
visited[module] = true
for _, dep := range module.directDeps {
if !visited[dep.module] {
walk(dep.module)
}
}
if module != topModule {
visiting = module
visit(module.logicModule)
}
}
walk(topModule)
}
func (c *Context) visitDepsDepthFirstIf(topModule *moduleInfo, pred func(Module) bool,
visit func(Module)) {
visited := make(map[*moduleInfo]bool)
var visiting *moduleInfo
defer func() {
if r := recover(); r != nil {
panic(newPanicErrorf(r, "VisitDepsDepthFirstIf(%s, %s, %s) for dependency %s",
topModule, funcName(pred), funcName(visit), visiting))
}
}()
var walk func(module *moduleInfo)
walk = func(module *moduleInfo) {
visited[module] = true
for _, dep := range module.directDeps {
if !visited[dep.module] {
walk(dep.module)
}
}
if module != topModule {
if pred(module.logicModule) {
visiting = module
visit(module.logicModule)
}
}
}
walk(topModule)
}
func (c *Context) sortedModuleNames() []string {
if c.cachedSortedModuleNames == nil {
c.cachedSortedModuleNames = make([]string, 0, len(c.moduleGroups))
@ -2414,13 +2359,43 @@ func (c *Context) VisitAllModulesIf(pred func(Module) bool,
func (c *Context) VisitDepsDepthFirst(module Module,
visit func(Module)) {
c.visitDepsDepthFirst(c.moduleInfo[module], visit)
topModule := c.moduleInfo[module]
var visiting *moduleInfo
defer func() {
if r := recover(); r != nil {
panic(newPanicErrorf(r, "VisitDepsDepthFirst(%s, %s) for dependency %s",
topModule, funcName(visit), visiting))
}
}()
c.walkDeps(topModule, nil, func(dep depInfo, parent *moduleInfo) {
visiting = dep.module
visit(dep.module.logicModule)
})
}
func (c *Context) VisitDepsDepthFirstIf(module Module,
pred func(Module) bool, visit func(Module)) {
c.visitDepsDepthFirstIf(c.moduleInfo[module], pred, visit)
topModule := c.moduleInfo[module]
var visiting *moduleInfo
defer func() {
if r := recover(); r != nil {
panic(newPanicErrorf(r, "VisitDepsDepthFirstIf(%s, %s, %s) for dependency %s",
topModule, funcName(pred), funcName(visit), visiting))
}
}()
c.walkDeps(topModule, nil, func(dep depInfo, parent *moduleInfo) {
if pred(dep.module.logicModule) {
visiting = dep.module
visit(dep.module.logicModule)
}
})
}
func (c *Context) PrimaryModule(module Module) Module {

View file

@ -166,17 +166,26 @@ func TestWalkDeps(t *testing.T) {
t.FailNow()
}
var output string
var outputDown string
var outputUp string
topModule := ctx.moduleGroups["A"].modules[0]
ctx.walkDeps(topModule,
func(module, parent Module) bool {
if module.(Walker).Walk() {
output += ctx.ModuleName(module)
func(dep depInfo, parent *moduleInfo) bool {
if dep.module.logicModule.(Walker).Walk() {
outputDown += ctx.ModuleName(dep.module.logicModule)
return true
}
return false
},
func(dep depInfo, parent *moduleInfo) {
if dep.module.logicModule.(Walker).Walk() {
outputUp += ctx.ModuleName(dep.module.logicModule)
}
})
if output != "CFG" {
t.Fatalf("unexpected walkDeps behaviour: %s\nshould be: CFG", output)
if outputDown != "CFG" {
t.Fatalf("unexpected walkDeps behaviour: %s\ndown should be: CFG", outputDown)
}
if outputUp != "GFC" {
t.Fatalf("unexpected walkDeps behaviour: %s\nup should be: GFC", outputUp)
}
}

View file

@ -155,11 +155,12 @@ type ModuleContext interface {
var _ BaseModuleContext = (*baseModuleContext)(nil)
type baseModuleContext struct {
context *Context
config interface{}
module *moduleInfo
errs []error
visiting depInfo
context *Context
config interface{}
module *moduleInfo
errs []error
visitingParent *moduleInfo
visitingDep depInfo
}
func (d *baseModuleContext) moduleInfo() *moduleInfo {
@ -255,11 +256,11 @@ func (m *baseModuleContext) OtherModuleErrorf(logicModule Module, format string,
func (m *baseModuleContext) OtherModuleDependencyTag(logicModule Module) DependencyTag {
// fast path for calling OtherModuleDependencyTag from inside VisitDirectDeps
if logicModule == m.visiting.module.logicModule {
return m.visiting.tag
if logicModule == m.visitingDep.module.logicModule {
return m.visitingDep.tag
}
for _, dep := range m.module.directDeps {
for _, dep := range m.visitingParent.directDeps {
if dep.module.logicModule == logicModule {
return dep.tag
}
@ -272,46 +273,91 @@ func (m *baseModuleContext) VisitDirectDeps(visit func(Module)) {
defer func() {
if r := recover(); r != nil {
panic(newPanicErrorf(r, "VisitDirectDeps(%s, %s) for dependency %s",
m.module, funcName(visit), m.visiting.module))
m.module, funcName(visit), m.visitingDep.module))
}
}()
m.visitingParent = m.module
for _, dep := range m.module.directDeps {
m.visiting = dep
m.visitingDep = dep
visit(dep.module.logicModule)
}
m.visiting = depInfo{}
m.visitingParent = nil
m.visitingDep = depInfo{}
}
func (m *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
defer func() {
if r := recover(); r != nil {
panic(newPanicErrorf(r, "VisitDirectDepsIf(%s, %s, %s) for dependency %s",
m.module, funcName(pred), funcName(visit), m.visiting.module))
m.module, funcName(pred), funcName(visit), m.visitingDep.module))
}
}()
m.visitingParent = m.module
for _, dep := range m.module.directDeps {
m.visiting = dep
m.visitingDep = dep
if pred(dep.module.logicModule) {
visit(dep.module.logicModule)
}
}
m.visiting = depInfo{}
m.visitingParent = nil
m.visitingDep = depInfo{}
}
func (m *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
m.context.visitDepsDepthFirst(m.module, visit)
defer func() {
if r := recover(); r != nil {
panic(newPanicErrorf(r, "VisitDepsDepthFirst(%s, %s) for dependency %s",
m.module, funcName(visit), m.visitingDep.module))
}
}()
m.context.walkDeps(m.module, nil, func(dep depInfo, parent *moduleInfo) {
m.visitingParent = parent
m.visitingDep = dep
visit(dep.module.logicModule)
})
m.visitingParent = nil
m.visitingDep = depInfo{}
}
func (m *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool,
visit func(Module)) {
m.context.visitDepsDepthFirstIf(m.module, pred, visit)
defer func() {
if r := recover(); r != nil {
panic(newPanicErrorf(r, "VisitDepsDepthFirstIf(%s, %s, %s) for dependency %s",
m.module, funcName(pred), funcName(visit), m.visitingDep.module))
}
}()
m.context.walkDeps(m.module, nil, func(dep depInfo, parent *moduleInfo) {
if pred(dep.module.logicModule) {
m.visitingParent = parent
m.visitingDep = dep
visit(dep.module.logicModule)
}
})
m.visitingParent = nil
m.visitingDep = depInfo{}
}
func (m *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
m.context.walkDeps(m.module, visit)
m.context.walkDeps(m.module, func(dep depInfo, parent *moduleInfo) bool {
m.visitingParent = parent
m.visitingDep = dep
return visit(dep.module.logicModule, parent.logicModule)
}, nil)
m.visitingParent = nil
m.visitingDep = depInfo{}
}
func (m *moduleContext) ModuleSubDir() string {

View file

@ -14,7 +14,10 @@
package blueprint
import "testing"
import (
"fmt"
"testing"
)
type visitModule struct {
properties struct {
@ -49,6 +52,9 @@ func visitDepsMutator(ctx BottomUpMutatorContext) {
func visitMutator(ctx TopDownMutatorContext) {
if m, ok := ctx.Module().(*visitModule); ok {
ctx.VisitDepsDepthFirst(func(dep Module) {
if ctx.OtherModuleDependencyTag(dep) != visitTagDep {
panic(fmt.Errorf("unexpected dependency tag on %q", ctx.OtherModuleName(dep)))
}
m.properties.VisitDepsDepthFirst = m.properties.VisitDepsDepthFirst + ctx.OtherModuleName(dep)
})
ctx.VisitDepsDepthFirstIf(func(dep Module) bool {