merger/fix.go
func FixLoads(f *rule.File, knownLoads []rule.LoadInfo) {
	knownFiles := make(map[string]bool)
	knownKinds := make(map[string]string)
	for _, l := range knownLoads {
		knownFiles[l.Name] = true
		for _, k := range l.Symbols {
			knownKinds[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.
	usedKinds := make(map[string]map[string]bool)
	for _, r := range f.Rules {
		kind := r.Kind()
		if file, ok := knownKinds[kind]; ok && !otherLoadedKinds[kind] {
			if usedKinds[file] == nil {
				usedKinds[file] = make(map[string]bool)
			}
			usedKinds[file][kind] = 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, usedKinds[file], knownKinds)
				first = false
			} else {
				fixLoad(l, file, nil, knownKinds)
			}
			if l.IsEmpty() {
				l.Delete()
			}
		}
		if first {
			load := fixLoad(nil, file, usedKinds[file], knownKinds)
			if load != nil {
				index := newLoadIndex(f, known.After)
				load.Insert(f, index)
			}
		}
	}
}
func FixLoads(f *rule.File, knownLoads []rule.LoadInfo) {
	knownFiles := make(map[string]bool)
	knownKinds := make(map[string]string)
	for _, l := range knownLoads {
		knownFiles[l.Name] = true
		for _, k := range l.Symbols {
			knownKinds[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.
	usedKinds := make(map[string]map[string]bool)
	for _, r := range f.Rules {
		kind := r.Kind()
		if file, ok := knownKinds[kind]; ok && !otherLoadedKinds[kind] {
			if usedKinds[file] == nil {
				usedKinds[file] = make(map[string]bool)
			}
			usedKinds[file][kind] = 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, usedKinds[file], knownKinds)
				first = false
			} else {
				fixLoad(l, file, nil, knownKinds)
			}
			if l.IsEmpty() {
				l.Delete()
			}
		}
		if first {
			load := fixLoad(nil, file, usedKinds[file], knownKinds)
			if load != nil {
				index := newLoadIndex(f, known.After)
				load.Insert(f, index)
			}
		}
	}
}
// FixLoads removes loads of unused go rules and adds loads of newly used rules.
// This should be called after FixFile and MergeFile, since symbols
// may be introduced that aren't loaded.
//
// This function calls File.Sync before processing loads.