func FixLoads()

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)
			}
		}
	}
}