rule/rule.go
func (f *File) Sync() {
	var loadInserts, loadDeletes, loadStmts []*stmt
	var r, w int
	for r, w = 0, 0; r < len(f.Loads); r++ {
		s := f.Loads[r]
		s.sync()
		if s.deleted {
			loadDeletes = append(loadDeletes, &s.stmt)
			continue
		}
		if s.inserted {
			loadInserts = append(loadInserts, &s.stmt)
			s.inserted = false
		} else {
			loadStmts = append(loadStmts, &s.stmt)
		}
		f.Loads[w] = s
		w++
	}
	f.Loads = f.Loads[:w]
	var ruleInserts, ruleDeletes, ruleStmts []*stmt
	for r, w = 0, 0; r < len(f.Rules); r++ {
		s := f.Rules[r]
		s.sync()
		if s.deleted {
			ruleDeletes = append(ruleDeletes, &s.stmt)
			continue
		}
		if s.inserted {
			ruleInserts = append(ruleInserts, &s.stmt)
			s.inserted = false
		} else {
			ruleStmts = append(ruleStmts, &s.stmt)
		}
		f.Rules[w] = s
		w++
	}
	f.Rules = f.Rules[:w]

	if f.function == nil {
		deletes := append(ruleDeletes, loadDeletes...)
		inserts := append(ruleInserts, loadInserts...)
		stmts := append(ruleStmts, loadStmts...)
		updateStmt(&f.File.Stmt, inserts, deletes, stmts)
	} else {
		updateStmt(&f.File.Stmt, loadInserts, loadDeletes, loadStmts)
		if f.function.hasPass && len(ruleInserts) > 0 {
			f.function.stmt.Body = []bzl.Expr{}
			f.function.hasPass = false
		}
		updateStmt(&f.function.stmt.Body, ruleInserts, ruleDeletes, ruleStmts)
		if len(f.function.stmt.Body) == 0 {
			f.function.stmt.Body = append(f.function.stmt.Body, &bzl.BranchStmt{Token: "pass"})
			f.function.hasPass = true
		}
		if !f.function.inserted {
			f.File.Stmt = append(f.File.Stmt, f.function.stmt)
			f.function.inserted = true
		}
	}
}
func (f *File) Sync() {
	var loadInserts, loadDeletes, loadStmts []*stmt
	var r, w int
	for r, w = 0, 0; r < len(f.Loads); r++ {
		s := f.Loads[r]
		s.sync()
		if s.deleted {
			loadDeletes = append(loadDeletes, &s.stmt)
			continue
		}
		if s.inserted {
			loadInserts = append(loadInserts, &s.stmt)
			s.inserted = false
		} else {
			loadStmts = append(loadStmts, &s.stmt)
		}
		f.Loads[w] = s
		w++
	}
	f.Loads = f.Loads[:w]
	var ruleInserts, ruleDeletes, ruleStmts []*stmt
	for r, w = 0, 0; r < len(f.Rules); r++ {
		s := f.Rules[r]
		s.sync()
		if s.deleted {
			ruleDeletes = append(ruleDeletes, &s.stmt)
			continue
		}
		if s.inserted {
			ruleInserts = append(ruleInserts, &s.stmt)
			s.inserted = false
		} else {
			ruleStmts = append(ruleStmts, &s.stmt)
		}
		f.Rules[w] = s
		w++
	}
	f.Rules = f.Rules[:w]

	if f.function == nil {
		deletes := append(ruleDeletes, loadDeletes...)
		inserts := append(ruleInserts, loadInserts...)
		stmts := append(ruleStmts, loadStmts...)
		updateStmt(&f.File.Stmt, inserts, deletes, stmts)
	} else {
		updateStmt(&f.File.Stmt, loadInserts, loadDeletes, loadStmts)
		if f.function.hasPass && len(ruleInserts) > 0 {
			f.function.stmt.Body = []bzl.Expr{}
			f.function.hasPass = false
		}
		updateStmt(&f.function.stmt.Body, ruleInserts, ruleDeletes, ruleStmts)
		if len(f.function.stmt.Body) == 0 {
			f.function.stmt.Body = append(f.function.stmt.Body, &bzl.BranchStmt{Token: "pass"})
			f.function.hasPass = true
		}
		if !f.function.inserted {
			f.File.Stmt = append(f.File.Stmt, f.function.stmt)
			f.function.inserted = true
		}
	}
}
// Sync writes all changes back to the wrapped syntax tree. This should be
// called after editing operations, before reading the syntax tree again.