in merger/fix.go [31:111]
func FixLoads(f *rule.File, knownLoads []rule.LoadInfo) {
knownFiles := make(map[string]bool)
knownSymbols := make(map[string]string)
for _, l := range knownLoads {
knownFiles[l.Name] = true
for _, k := range l.Symbols {
knownSymbols[k] = l.Name
}
}
// Sync the file. We need File.Loads and File.Rules to contain inserted
// statements and not deleted statements.
f.Sync()
// Scan load statements in the file. Keep track of loads of known files,
// since these may be changed. Keep track of symbols loaded from unknown
// files; we will not add loads for these.
var loads []*rule.Load
otherLoadedKinds := make(map[string]bool)
for _, l := range f.Loads {
if knownFiles[l.Name()] {
loads = append(loads, l)
continue
}
for _, sym := range l.Symbols() {
otherLoadedKinds[sym] = true
}
}
// Make a map of all the symbols from known files used in this file.
usedSymbols := make(map[string]map[string]bool)
bzl.Walk(f.File, func(x bzl.Expr, stk []bzl.Expr) {
ce, ok := x.(*bzl.CallExpr)
if !ok {
return
}
id, ok := ce.X.(*bzl.Ident)
if !ok {
return
}
file, ok := knownSymbols[id.Name]
if !ok || otherLoadedKinds[id.Name] {
return
}
if usedSymbols[file] == nil {
usedSymbols[file] = make(map[string]bool)
}
usedSymbols[file][id.Name] = true
})
// Fix the load statements. The order is important, so we iterate over
// knownLoads instead of knownFiles.
for _, known := range knownLoads {
file := known.Name
first := true
for _, l := range loads {
if l.Name() != file {
continue
}
if first {
fixLoad(l, file, usedSymbols[file], knownSymbols)
first = false
} else {
fixLoad(l, file, nil, knownSymbols)
}
if l.IsEmpty() {
l.Delete()
}
}
if first {
load := fixLoad(nil, file, usedSymbols[file], knownSymbols)
if load != nil {
index := newLoadIndex(f, known.After)
load.Insert(f, index)
}
}
}
}