Merge changes I648ef95f,Iadb72a5a,Ib073f6ec into main

* changes:
  Don't sort the results of TransitionMutator.Split
  Apply outgoing transitions when adding dependencies
  Delete transition variation when no matching variant was found
This commit is contained in:
Colin Cross 2024-05-08 23:43:56 +00:00 committed by Gerrit Code Review
commit 5bc2b73593
3 changed files with 63 additions and 25 deletions

View file

@ -1872,34 +1872,47 @@ func (c *Context) findReverseDependency(module *moduleInfo, config any, destName
}}
}
// applyIncomingTransitions takes a variationMap being used to add a dependency on a module in a moduleGroup
// and applies the IncomingTransition method of each completed TransitionMutator to modify the requested variation.
// It finds a variant that existed before the TransitionMutator ran that is a subset of the requested variant to
// use as the module context for IncomingTransition.
func (c *Context) applyIncomingTransitions(config any, group *moduleGroup, variant variationMap, requestedVariations []Variation) {
// applyTransitions takes a variationMap being used to add a dependency on a module in a moduleGroup
// and applies the OutgoingTransition and IncomingTransition methods of each completed TransitionMutator to
// modify the requested variation. It finds a variant that existed before the TransitionMutator ran that is
// a subset of the requested variant to use as the module context for IncomingTransition.
func (c *Context) applyTransitions(config any, module *moduleInfo, group *moduleGroup, variant variationMap,
requestedVariations []Variation) {
for _, transitionMutator := range c.transitionMutators {
if len(transitionMutator.inputVariants[group]) == 0 {
// The transition mutator didn't apply anything to the target module, remove the variation unless it
// was explicitly requested when adding the dependency.
if !slices.ContainsFunc(requestedVariations, func(v Variation) bool { return v.Mutator == transitionMutator.name }) {
delete(variant, transitionMutator.name)
// Apply the outgoing transition if it was not explicitly requested.
explicitlyRequested := slices.ContainsFunc(requestedVariations, func(variation Variation) bool {
return variation.Mutator == transitionMutator.name
})
sourceVariation := variant[transitionMutator.name]
outgoingVariation := sourceVariation
if !explicitlyRequested {
ctx := &outgoingTransitionContextImpl{
transitionContextImpl{context: c, source: module, dep: nil, depTag: nil, config: config},
}
continue
outgoingVariation = transitionMutator.mutator.OutgoingTransition(ctx, sourceVariation)
}
// Find an appropriate module to use as the context for the IncomingTransition.
appliedIncomingTransition := false
for _, inputVariant := range transitionMutator.inputVariants[group] {
if inputVariant.variant.variations.subsetOf(variant) {
sourceVariation := variant[transitionMutator.name]
// Apply the incoming transition.
ctx := &incomingTransitionContextImpl{
transitionContextImpl{context: c, source: nil, dep: inputVariant,
depTag: nil, config: config},
}
outgoingVariation := transitionMutator.mutator.IncomingTransition(ctx, sourceVariation)
variant[transitionMutator.name] = outgoingVariation
finalVariation := transitionMutator.mutator.IncomingTransition(ctx, outgoingVariation)
variant[transitionMutator.name] = finalVariation
appliedIncomingTransition = true
break
}
}
if !appliedIncomingTransition && !explicitlyRequested {
// The transition mutator didn't apply anything to the target variant, remove the variation unless it
// was explicitly requested when adding the dependency.
delete(variant, transitionMutator.name)
}
}
}
@ -1927,7 +1940,7 @@ func (c *Context) findVariant(module *moduleInfo, config any,
newVariant[v.Mutator] = v.Variation
}
c.applyIncomingTransitions(config, possibleDeps, newVariant, requestedVariations)
c.applyTransitions(config, module, possibleDeps, newVariant, requestedVariations)
check := func(variant variationMap) bool {
if far {
@ -3001,7 +3014,7 @@ func (c *Context) runMutator(config interface{}, mutator *mutatorInfo,
// Update module group to contain newly split variants
if module.splitModules != nil {
if isTransitionMutator {
// For transition mutators, save the pre-split variant for reusing later in applyIncomingTransitions.
// For transition mutators, save the pre-split variant for reusing later in applyTransitions.
transitionMutatorInputVariants[group] = append(transitionMutatorInputVariants[group], module)
}
group.modules, i = spliceModules(group.modules, i, module.splitModules)

View file

@ -186,8 +186,11 @@ func (t *transitionMutatorImpl) topDownMutator(mctx TopDownMutatorContext) {
// and modules that directly depend on it. Since this is a top-down mutator,
// all modules that directly depend on this module have already been processed
// so no locking is necessary.
module.transitionVariations = addToStringListIfNotPresent(module.transitionVariations, mutatorSplits...)
// Sort the module transitions, but keep the mutatorSplits in the order returned
// by Split, as the order can be significant when inter-variant dependencies are
// used.
sort.Strings(module.transitionVariations)
module.transitionVariations = addToStringListIfNotPresent(mutatorSplits, module.transitionVariations...)
outgoingTransitionCache := make([][]string, len(module.transitionVariations))
for srcVariationIndex, srcVariation := range module.transitionVariations {

View file

@ -60,7 +60,7 @@ const testTransitionBp = `
transition_module {
name: "A",
deps: ["B", "C"],
split: ["a", "b"],
split: ["b", "a"],
}
transition_module {
@ -84,6 +84,10 @@ const testTransitionBp = `
transition_module {
name: "E",
}
transition_module {
name: "F"
}
`
func getTransitionModule(ctx *Context, name, variant string) *transitionModule {
@ -128,7 +132,7 @@ func TestTransition(t *testing.T) {
assertNoErrors(t, errs)
// Module A uses Split to create a and b variants
checkTransitionVariants(t, ctx, "A", []string{"a", "b"})
checkTransitionVariants(t, ctx, "A", []string{"b", "a"})
// Module B inherits a and b variants from A
checkTransitionVariants(t, ctx, "B", []string{"", "a", "b"})
// Module C inherits a and b variants from A, but gets an outgoing c variant from B
@ -137,6 +141,8 @@ func TestTransition(t *testing.T) {
checkTransitionVariants(t, ctx, "D", []string{"", "d"})
// Module E inherits d from D
checkTransitionVariants(t, ctx, "E", []string{"", "d"})
// Module F is untouched
checkTransitionVariants(t, ctx, "F", []string{""})
A_a := getTransitionModule(ctx, "A", "a")
A_b := getTransitionModule(ctx, "A", "b")
@ -147,6 +153,7 @@ func TestTransition(t *testing.T) {
C_c := getTransitionModule(ctx, "C", "c")
D_d := getTransitionModule(ctx, "D", "d")
E_d := getTransitionModule(ctx, "E", "d")
F := getTransitionModule(ctx, "F", "")
checkTransitionDeps(t, ctx, A_a, "B(a)", "C(a)")
checkTransitionDeps(t, ctx, A_b, "B(b)", "C(b)")
@ -157,6 +164,7 @@ func TestTransition(t *testing.T) {
checkTransitionDeps(t, ctx, C_c, "D(d)")
checkTransitionDeps(t, ctx, D_d, "E(d)")
checkTransitionDeps(t, ctx, E_d)
checkTransitionDeps(t, ctx, F)
checkTransitionMutate(t, A_a, "a")
checkTransitionMutate(t, A_b, "b")
@ -167,15 +175,16 @@ func TestTransition(t *testing.T) {
checkTransitionMutate(t, C_c, "c")
checkTransitionMutate(t, D_d, "d")
checkTransitionMutate(t, E_d, "d")
checkTransitionMutate(t, F, "")
}
func TestPostTransitionDeps(t *testing.T) {
ctx, errs := testTransition(fmt.Sprintf(testTransitionBp,
`post_transition_deps: ["D:late", "E:d"],`))
`post_transition_deps: ["C", "D:late", "E:d", "F"],`))
assertNoErrors(t, errs)
// Module A uses Split to create a and b variants
checkTransitionVariants(t, ctx, "A", []string{"a", "b"})
checkTransitionVariants(t, ctx, "A", []string{"b", "a"})
// Module B inherits a and b variants from A
checkTransitionVariants(t, ctx, "B", []string{"", "a", "b"})
// Module C inherits a and b variants from A, but gets an outgoing c variant from B
@ -184,6 +193,8 @@ func TestPostTransitionDeps(t *testing.T) {
checkTransitionVariants(t, ctx, "D", []string{"", "d"})
// Module E inherits d from D
checkTransitionVariants(t, ctx, "E", []string{"", "d"})
// Module F is untouched
checkTransitionVariants(t, ctx, "F", []string{""})
A_a := getTransitionModule(ctx, "A", "a")
A_b := getTransitionModule(ctx, "A", "b")
@ -194,16 +205,23 @@ func TestPostTransitionDeps(t *testing.T) {
C_c := getTransitionModule(ctx, "C", "c")
D_d := getTransitionModule(ctx, "D", "d")
E_d := getTransitionModule(ctx, "E", "d")
F := getTransitionModule(ctx, "F", "")
checkTransitionDeps(t, ctx, A_a, "B(a)", "C(a)")
checkTransitionDeps(t, ctx, A_b, "B(b)", "C(b)")
checkTransitionDeps(t, ctx, B_a, "C(c)", "D(d)", "E(d)")
checkTransitionDeps(t, ctx, B_b, "C(c)", "D(d)", "E(d)")
// Verify post-mutator dependencies added to B. The first C(c) is a pre-mutator dependency.
// C(c) was added by C and rewritten by OutgoingTransition on B
// D(d) was added by D:late and rewritten by IncomingTransition on D
// E(d) was added by E:d
// F() was added by F, and ignored the existing variation on B
checkTransitionDeps(t, ctx, B_a, "C(c)", "C(c)", "D(d)", "E(d)", "F()")
checkTransitionDeps(t, ctx, B_b, "C(c)", "C(c)", "D(d)", "E(d)", "F()")
checkTransitionDeps(t, ctx, C_a, "D(d)")
checkTransitionDeps(t, ctx, C_b, "D(d)")
checkTransitionDeps(t, ctx, C_c, "D(d)")
checkTransitionDeps(t, ctx, D_d, "E(d)")
checkTransitionDeps(t, ctx, E_d)
checkTransitionDeps(t, ctx, F)
checkTransitionMutate(t, A_a, "a")
checkTransitionMutate(t, A_b, "b")
@ -214,6 +232,7 @@ func TestPostTransitionDeps(t *testing.T) {
checkTransitionMutate(t, C_c, "c")
checkTransitionMutate(t, D_d, "d")
checkTransitionMutate(t, E_d, "d")
checkTransitionMutate(t, F, "")
}
func TestPostTransitionDepsMissingVariant(t *testing.T) {
@ -290,7 +309,10 @@ func postTransitionDepsMutator(mctx BottomUpMutatorContext) {
if m, ok := mctx.Module().(*transitionModule); ok {
for _, dep := range m.properties.Post_transition_deps {
module, variation, _ := strings.Cut(dep, ":")
variations := []Variation{{"transition", variation}}
var variations []Variation
if variation != "" {
variations = append(variations, Variation{"transition", variation})
}
mctx.AddVariationDependencies(variations, walkerDepsTag{follow: true}, module)
}
}