rule/rule.go
func ScanASTBody(pkg, defName string, bzlFile *bzl.File) *File {
	f := &File{
		File: bzlFile,
		Pkg:  pkg,
		Path: bzlFile.Path,
	}
	var defStmt *bzl.DefStmt
	f.Rules, f.Loads, defStmt = scanExprs(defName, bzlFile.Stmt)
	if defStmt != nil {
		f.Rules, _, _ = scanExprs("", defStmt.Body)
		f.function = &function{
			stmt:     defStmt,
			inserted: true,
		}
		if len(defStmt.Body) == 1 {
			if v, ok := defStmt.Body[0].(*bzl.BranchStmt); ok && v.Token == "pass" {
				f.function.hasPass = true
			}
		}
	} else if defName != "" {
		f.function = &function{
			stmt:     &bzl.DefStmt{Name: defName},
			inserted: false,
		}
	}
	f.Directives = ParseDirectives(bzlFile)
	return f
}
func ScanASTBody(pkg, defName string, bzlFile *bzl.File) *File {
	f := &File{
		File: bzlFile,
		Pkg:  pkg,
		Path: bzlFile.Path,
	}
	var defStmt *bzl.DefStmt
	f.Rules, f.Loads, defStmt = scanExprs(defName, bzlFile.Stmt)
	if defStmt != nil {
		f.Rules, _, _ = scanExprs("", defStmt.Body)
		f.function = &function{
			stmt:     defStmt,
			inserted: true,
		}
		if len(defStmt.Body) == 1 {
			if v, ok := defStmt.Body[0].(*bzl.BranchStmt); ok && v.Token == "pass" {
				f.function.hasPass = true
			}
		}
	} else if defName != "" {
		f.function = &function{
			stmt:     &bzl.DefStmt{Name: defName},
			inserted: false,
		}
	}
	f.Directives = ParseDirectives(bzlFile)
	return f
}
// ScanASTBody creates a File wrapped around the given syntax tree. It will also
// scan the AST for a function matching the given defName, and if the function
// does not exist it will create a new one and mark it to be added to the File
// the next time Sync is called.