// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"go/types"
	"io"
	"log"
	"os"
	"sort"
	"strconv"
	"strings"
	"sync"

	"golang.org/x/tools/cmd/guru/serial"
	"golang.org/x/tools/go/buildutil"
	"golang.org/x/tools/go/loader"
	"golang.org/x/tools/imports"
	"golang.org/x/tools/refactor/importgraph"
)

// The referrers function reports all identifiers that resolve to the same object
// as the queried identifier, within any package in the workspace.
func referrers(q *Query) error {
	fset := token.NewFileSet()
	lconf := loader.Config{Fset: fset, Build: q.Build}
	allowErrors(&lconf)

	if _, err := importQueryPackage(q.Pos, &lconf); err != nil {
		return err
	}

	// Load tests of the query package
	// even if the query location is not in the tests.
	for path := range lconf.ImportPkgs {
		lconf.ImportPkgs[path] = true
	}

	// Load/parse/type-check the query package.
	lprog, err := lconf.Load()
	if err != nil {
		return err
	}

	qpos, err := parseQueryPos(lprog, q.Pos, false)
	if err != nil {
		return err
	}

	id, _ := qpos.path[0].(*ast.Ident)
	if id == nil {
		return fmt.Errorf("no identifier here")
	}

	obj := qpos.info.ObjectOf(id)
	if obj == nil {
		// Happens for y in "switch y := x.(type)",
		// the package declaration,
		// and unresolved identifiers.
		if _, ok := qpos.path[1].(*ast.File); ok { // package decl?
			return packageReferrers(q, qpos.info.Pkg.Path())
		}
		return fmt.Errorf("no object for identifier: %T", qpos.path[1])
	}

	// Imported package name?
	if pkgname, ok := obj.(*types.PkgName); ok {
		return packageReferrers(q, pkgname.Imported().Path())
	}

	if obj.Pkg() == nil {
		return fmt.Errorf("references to predeclared %q are everywhere!", obj.Name())
	}

	q.Output(fset, &referrersInitialResult{
		qinfo: qpos.info,
		obj:   obj,
	})

	// For a globally accessible object defined in package P, we
	// must load packages that depend on P.  Specifically, for a
	// package-level object, we need load only direct importers
	// of P, but for a field or method, we must load
	// any package that transitively imports P.

	if global, pkglevel := classify(obj); global {
		if pkglevel {
			return globalReferrersPkgLevel(q, obj, fset)
		}
		// We'll use the the object's position to identify it in the larger program.
		objposn := fset.Position(obj.Pos())
		defpkg := obj.Pkg().Path() // defining package
		return globalReferrers(q, qpos.info.Pkg.Path(), defpkg, objposn)
	}

	outputUses(q, fset, usesOf(obj, qpos.info), obj.Pkg())

	return nil // success
}

// classify classifies objects by how far
// we have to look to find references to them.
func classify(obj types.Object) (global, pkglevel bool) {
	if obj.Exported() {
		if obj.Parent() == nil {
			// selectable object (field or method)
			return true, false
		}
		if obj.Parent() == obj.Pkg().Scope() {
			// lexical object (package-level var/const/func/type)
			return true, true
		}
	}
	// object with unexported named or defined in local scope
	return false, false
}

// packageReferrers reports all references to the specified package
// throughout the workspace.
func packageReferrers(q *Query, path string) error {
	// Scan the workspace and build the import graph.
	// Ignore broken packages.
	_, rev, _ := importgraph.Build(q.Build)

	// Find the set of packages that directly import the query package.
	// Only those packages need typechecking of function bodies.
	users := rev[path]

	// Load the larger program.
	fset := token.NewFileSet()
	lconf := loader.Config{
		Fset:  fset,
		Build: q.Build,
		TypeCheckFuncBodies: func(p string) bool {
			return users[strings.TrimSuffix(p, "_test")]
		},
	}
	allowErrors(&lconf)

	// The importgraph doesn't treat external test packages
	// as separate nodes, so we must use ImportWithTests.
	for path := range users {
		lconf.ImportWithTests(path)
	}

	// Subtle!  AfterTypeCheck needs no mutex for qpkg because the
	// topological import order gives us the necessary happens-before edges.
	// TODO(adonovan): what about import cycles?
	var qpkg *types.Package

	// For efficiency, we scan each package for references
	// just after it has been type-checked.  The loader calls
	// AfterTypeCheck (concurrently), providing us with a stream of
	// packages.
	lconf.AfterTypeCheck = func(info *loader.PackageInfo, files []*ast.File) {
		// AfterTypeCheck may be called twice for the same package due to augmentation.

		if info.Pkg.Path() == path && qpkg == nil {
			// Found the package of interest.
			qpkg = info.Pkg
			fakepkgname := types.NewPkgName(token.NoPos, qpkg, qpkg.Name(), qpkg)
			q.Output(fset, &referrersInitialResult{
				qinfo: info,
				obj:   fakepkgname, // bogus
			})
		}

		// Only inspect packages that directly import the
		// declaring package (and thus were type-checked).
		if lconf.TypeCheckFuncBodies(info.Pkg.Path()) {
			// Find PkgNames that refer to qpkg.
			// TODO(adonovan): perhaps more useful would be to show imports
			// of the package instead of qualified identifiers.
			var refs []*ast.Ident
			for id, obj := range info.Uses {
				if obj, ok := obj.(*types.PkgName); ok && obj.Imported() == qpkg {
					refs = append(refs, id)
				}
			}
			outputUses(q, fset, refs, info.Pkg)
		}

		clearInfoFields(info) // save memory
	}

	lconf.Load() // ignore error

	if qpkg == nil {
		log.Fatalf("query package %q not found during reloading", path)
	}

	return nil
}

func usesOf(queryObj types.Object, info *loader.PackageInfo) []*ast.Ident {
	var refs []*ast.Ident
	for id, obj := range info.Uses {
		if sameObj(queryObj, obj) {
			refs = append(refs, id)
		}
	}
	return refs
}

// outputUses outputs a result describing refs, which appear in the package denoted by info.
func outputUses(q *Query, fset *token.FileSet, refs []*ast.Ident, pkg *types.Package) {
	if len(refs) > 0 {
		sort.Sort(byNamePos{fset, refs})
		q.Output(fset, &referrersPackageResult{
			pkg:   pkg,
			build: q.Build,
			fset:  fset,
			refs:  refs,
		})
	}
}

// globalReferrers reports references throughout the entire workspace to the
// object (a field or method) at the specified source position.
// Its defining package is defpkg, and the query package is qpkg.
func globalReferrers(q *Query, qpkg, defpkg string, objposn token.Position) error {
	// Scan the workspace and build the import graph.
	// Ignore broken packages.
	_, rev, _ := importgraph.Build(q.Build)

	// Find the set of packages that depend on defpkg.
	// Only function bodies in those packages need type-checking.
	users := rev.Search(defpkg) // transitive importers

	// Prepare to load the larger program.
	fset := token.NewFileSet()
	lconf := loader.Config{
		Fset:  fset,
		Build: q.Build,
		TypeCheckFuncBodies: func(p string) bool {
			return users[strings.TrimSuffix(p, "_test")]
		},
	}
	allowErrors(&lconf)

	// The importgraph doesn't treat external test packages
	// as separate nodes, so we must use ImportWithTests.
	for path := range users {
		lconf.ImportWithTests(path)
	}

	// The remainder of this function is somewhat tricky because it
	// operates on the concurrent stream of packages observed by the
	// loader's AfterTypeCheck hook.  Most of guru's helper
	// functions assume the entire program has already been loaded,
	// so we can't use them here.
	// TODO(adonovan): smooth things out once the other changes have landed.

	// Results are reported concurrently from within the
	// AfterTypeCheck hook.  The program may provide a useful stream
	// of information even if the user doesn't let the program run
	// to completion.

	var (
		mu   sync.Mutex
		qobj types.Object
	)

	// For efficiency, we scan each package for references
	// just after it has been type-checked.  The loader calls
	// AfterTypeCheck (concurrently), providing us with a stream of
	// packages.
	lconf.AfterTypeCheck = func(info *loader.PackageInfo, files []*ast.File) {
		// AfterTypeCheck may be called twice for the same package due to augmentation.

		// Only inspect packages that depend on the declaring package
		// (and thus were type-checked).
		if lconf.TypeCheckFuncBodies(info.Pkg.Path()) {
			// Record the query object and its package when we see it.
			mu.Lock()
			if qobj == nil && info.Pkg.Path() == defpkg {
				// Find the object by its position (slightly ugly).
				qobj = findObject(fset, &info.Info, objposn)
				if qobj == nil {
					// It really ought to be there;
					// we found it once already.
					log.Fatalf("object at %s not found in package %s",
						objposn, defpkg)
				}
			}
			obj := qobj
			mu.Unlock()

			// Look for references to the query object.
			if obj != nil {
				outputUses(q, fset, usesOf(obj, info), info.Pkg)
			}
		}

		clearInfoFields(info) // save memory
	}

	lconf.Load() // ignore error

	if qobj == nil {
		log.Fatal("query object not found during reloading")
	}

	return nil // success
}

// globalReferrersPkgLevel reports references throughout the entire workspace to the package-level object obj.
// It assumes that the query object itself has already been reported.
func globalReferrersPkgLevel(q *Query, obj types.Object, fset *token.FileSet) error {
	// globalReferrersPkgLevel uses go/ast and friends instead of go/types.
	// This affords a considerable performance benefit.
	// It comes at the cost of some code complexity.
	//
	// Here's a high level summary.
	//
	// The goal is to find references to the query object p.Q.
	// There are several possible scenarios, each handled differently.
	//
	// 1. We are looking in a package other than p, and p is not dot-imported.
	//    This is the simplest case. Q must be referred to as n.Q,
	//    where n is the name under which p is imported.
	//    We look at all imports of p to gather all names under which it is imported.
	//    (In the typical case, it is imported only once, under its default name.)
	//    Then we look at all selector expressions and report any matches.
	//
	// 2. We are looking in a package other than p, and p is dot-imported.
	//    In this case, Q will be referred to just as Q.
	//    Furthermore, go/ast's object resolution will not be able to resolve
	//    Q to any other object, unlike any local (file- or function- or block-scoped) object.
	//    So we look at all matching identifiers and report all unresolvable ones.
	//
	// 3. We are looking in package p.
	//    (Care must be taken to separate p and p_test (an xtest package),
	//    and make sure that they are treated as separate packages.)
	//    In this case, we give go/ast the entire package for object resolution,
	//    instead of going file by file.
	//    We then iterate over all identifiers that resolve to the query object.
	//    (The query object itself has already been reported, so we don't re-report it.)
	//
	// We always skip all files that don't contain the string Q, as they cannot be
	// relevant to finding references to Q.
	//
	// We parse all files leniently. In the presence of parsing errors, results are best-effort.

	// Scan the workspace and build the import graph.
	// Ignore broken packages.
	_, rev, _ := importgraph.Build(q.Build)

	// Find the set of packages that directly import defpkg.
	defpkg := obj.Pkg().Path()
	defpkg = strings.TrimSuffix(defpkg, "_test") // package x_test actually has package name x
	defpkg = imports.VendorlessPath(defpkg)      // remove vendor goop

	users := rev[defpkg]
	if len(users) == 0 {
		users = make(map[string]bool)
	}
	// We also need to check defpkg itself, and its xtests.
	// For the reverse graph packages, we process xtests with the main package.
	// defpkg gets special handling; we must distinguish between in-package vs out-of-package.
	// To make the control flow below simpler, add defpkg and defpkg xtest placeholders.
	// Use "!test" instead of "_test" because "!" is not a valid character in an import path.
	// (More precisely, it is not guaranteed to be a valid character in an import path,
	// so it is unlikely that it will be in use. See https://golang.org/ref/spec#Import_declarations.)
	users[defpkg] = true
	users[defpkg+"!test"] = true

	cwd, err := os.Getwd()
	if err != nil {
		return err
	}

	defname := obj.Pkg().Name()                    // name of defining package, used for imports using import path only
	isxtest := strings.HasSuffix(defname, "_test") // indicates whether the query object is defined in an xtest package

	name := obj.Name()
	namebytes := []byte(name)          // byte slice version of query object name, for early filtering
	objpos := fset.Position(obj.Pos()) // position of query object, used to prevent re-emitting original decl

	sema := make(chan struct{}, 20) // counting semaphore to limit I/O concurrency
	var wg sync.WaitGroup

	for u := range users {
		u := u
		wg.Add(1)
		go func() {
			defer wg.Done()

			uIsXTest := strings.HasSuffix(u, "!test") // indicates whether this package is the special defpkg xtest package
			u = strings.TrimSuffix(u, "!test")

			// Resolve package.
			sema <- struct{}{} // acquire token
			pkg, err := q.Build.Import(u, cwd, build.IgnoreVendor)
			<-sema // release token
			if err != nil {
				return
			}

			// If we're not in the query package,
			// the object is in another package regardless,
			// so we want to process all files.
			// If we are in the query package,
			// we want to only process the files that are
			// part of that query package;
			// that set depends on whether the query package itself is an xtest.
			inQueryPkg := u == defpkg && isxtest == uIsXTest
			var files []string
			if !inQueryPkg || !isxtest {
				files = append(files, pkg.GoFiles...)
				files = append(files, pkg.TestGoFiles...)
				files = append(files, pkg.CgoFiles...) // use raw cgo files, as we're only parsing
			}
			if !inQueryPkg || isxtest {
				files = append(files, pkg.XTestGoFiles...)
			}

			if len(files) == 0 {
				return
			}

			var deffiles map[string]*ast.File
			if inQueryPkg {
				deffiles = make(map[string]*ast.File)
			}

			buf := new(bytes.Buffer) // reusable buffer for reading files

			for _, file := range files {
				if !buildutil.IsAbsPath(q.Build, file) {
					file = buildutil.JoinPath(q.Build, pkg.Dir, file)
				}
				buf.Reset()
				sema <- struct{}{} // acquire token
				src, err := readFile(q.Build, file, buf)
				<-sema // release token
				if err != nil {
					continue
				}

				// Fast path: If the object's name isn't present anywhere in the source, ignore the file.
				if !bytes.Contains(src, namebytes) {
					continue
				}

				if inQueryPkg {
					// If we're in the query package, we defer final processing until we have
					// parsed all of the candidate files in the package.
					// Best effort; allow errors and use what we can from what remains.
					f, _ := parser.ParseFile(fset, file, src, parser.AllErrors)
					if f != nil {
						deffiles[file] = f
					}
					continue
				}

				// We aren't in the query package. Go file by file.

				// Parse out only the imports, to check whether the defining package
				// was imported, and if so, under what names.
				// Best effort; allow errors and use what we can from what remains.
				f, _ := parser.ParseFile(fset, file, src, parser.ImportsOnly|parser.AllErrors)
				if f == nil {
					continue
				}

				// pkgnames is the set of names by which defpkg is imported in this file.
				// (Multiple imports in the same file are legal but vanishingly rare.)
				pkgnames := make([]string, 0, 1)
				var isdotimport bool
				for _, imp := range f.Imports {
					path, err := strconv.Unquote(imp.Path.Value)
					if err != nil || path != defpkg {
						continue
					}
					switch {
					case imp.Name == nil:
						pkgnames = append(pkgnames, defname)
					case imp.Name.Name == ".":
						isdotimport = true
					default:
						pkgnames = append(pkgnames, imp.Name.Name)
					}
				}
				if len(pkgnames) == 0 && !isdotimport {
					// Defining package not imported, bail.
					continue
				}

				// Re-parse the entire file.
				// Parse errors are ok; we'll do the best we can with a partial AST, if we have one.
				f, _ = parser.ParseFile(fset, file, src, parser.AllErrors)
				if f == nil {
					continue
				}

				// Walk the AST looking for references.
				var refs []*ast.Ident
				ast.Inspect(f, func(n ast.Node) bool {
					// Check selector expressions.
					// If the selector matches the target name,
					// and the expression is one of the names
					// that the defining package was imported under,
					// then we have a match.
					if sel, ok := n.(*ast.SelectorExpr); ok && sel.Sel.Name == name {
						if id, ok := sel.X.(*ast.Ident); ok {
							for _, n := range pkgnames {
								if n == id.Name {
									refs = append(refs, sel.Sel)
									// Don't recurse further, to avoid duplicate entries
									// from the dot import check below.
									return false
								}
							}
						}
					}
					// Dot imports are special.
					// Objects imported from the defining package are placed in the package scope.
					// go/ast does not resolve them to an object.
					// At all other scopes (file, local), go/ast can do the resolution.
					// So we're looking for object-free idents with the right name.
					// The only other way to get something with the right name at the package scope
					// is to *be* the defining package. We handle that case separately (inQueryPkg).
					if isdotimport {
						if id, ok := n.(*ast.Ident); ok && id.Obj == nil && id.Name == name {
							refs = append(refs, id)
							return false
						}
					}
					return true
				})

				// Emit any references we found.
				if len(refs) > 0 {
					q.Output(fset, &referrersPackageResult{
						pkg:   types.NewPackage(pkg.ImportPath, pkg.Name),
						build: q.Build,
						fset:  fset,
						refs:  refs,
					})
				}
			}

			// If we're in the query package, we've now collected all the files in the package.
			// (Or at least the ones that might contain references to the object.)
			// Find and emit refs.
			if inQueryPkg {
				// Bundle the files together into a package.
				// This does package-level object resolution.
				qpkg, _ := ast.NewPackage(fset, deffiles, nil, nil)
				// Look up the query object; we know that it is defined in the package scope.
				pkgobj := qpkg.Scope.Objects[name]
				if pkgobj == nil {
					panic("missing defpkg object for " + defpkg + "." + name)
				}
				// Find all references to the query object.
				var refs []*ast.Ident
				ast.Inspect(qpkg, func(n ast.Node) bool {
					if id, ok := n.(*ast.Ident); ok {
						// Check both that this is a reference to the query object
						// and that it is not the query object itself;
						// the query object itself was already emitted.
						if id.Obj == pkgobj && objpos != fset.Position(id.Pos()) {
							refs = append(refs, id)
							return false
						}
					}
					return true
				})
				if len(refs) > 0 {
					q.Output(fset, &referrersPackageResult{
						pkg:   types.NewPackage(pkg.ImportPath, pkg.Name),
						build: q.Build,
						fset:  fset,
						refs:  refs,
					})
				}
				deffiles = nil // allow GC
			}
		}()
	}

	wg.Wait()

	return nil
}

// findObject returns the object defined at the specified position.
func findObject(fset *token.FileSet, info *types.Info, objposn token.Position) types.Object {
	good := func(obj types.Object) bool {
		if obj == nil {
			return false
		}
		posn := fset.Position(obj.Pos())
		return posn.Filename == objposn.Filename && posn.Offset == objposn.Offset
	}
	for _, obj := range info.Defs {
		if good(obj) {
			return obj
		}
	}
	for _, obj := range info.Implicits {
		if good(obj) {
			return obj
		}
	}
	return nil
}

// same reports whether x and y are identical, or both are PkgNames
// that import the same Package.
//
func sameObj(x, y types.Object) bool {
	if x == y {
		return true
	}
	if x, ok := x.(*types.PkgName); ok {
		if y, ok := y.(*types.PkgName); ok {
			return x.Imported() == y.Imported()
		}
	}
	return false
}

func clearInfoFields(info *loader.PackageInfo) {
	// TODO(adonovan): opt: save memory by eliminating unneeded scopes/objects.
	// (Requires go/types change for Go 1.7.)
	//   info.Pkg.Scope().ClearChildren()

	// Discard the file ASTs and their accumulated type
	// information to save memory.
	info.Files = nil
	info.Defs = make(map[*ast.Ident]types.Object)
	info.Uses = make(map[*ast.Ident]types.Object)
	info.Implicits = make(map[ast.Node]types.Object)

	// Also, disable future collection of wholly unneeded
	// type information for the package in case there is
	// more type-checking to do (augmentation).
	info.Types = nil
	info.Scopes = nil
	info.Selections = nil
}

// -------- utils --------

// An deterministic ordering for token.Pos that doesn't
// depend on the order in which packages were loaded.
func lessPos(fset *token.FileSet, x, y token.Pos) bool {
	fx := fset.File(x)
	fy := fset.File(y)
	if fx != fy {
		return fx.Name() < fy.Name()
	}
	return x < y
}

type byNamePos struct {
	fset *token.FileSet
	ids  []*ast.Ident
}

func (p byNamePos) Len() int      { return len(p.ids) }
func (p byNamePos) Swap(i, j int) { p.ids[i], p.ids[j] = p.ids[j], p.ids[i] }
func (p byNamePos) Less(i, j int) bool {
	return lessPos(p.fset, p.ids[i].NamePos, p.ids[j].NamePos)
}

// referrersInitialResult is the initial result of a "referrers" query.
type referrersInitialResult struct {
	qinfo *loader.PackageInfo
	obj   types.Object // object it denotes
}

func (r *referrersInitialResult) PrintPlain(printf printfFunc) {
	printf(r.obj, "references to %s",
		types.ObjectString(r.obj, types.RelativeTo(r.qinfo.Pkg)))
}

func (r *referrersInitialResult) JSON(fset *token.FileSet) []byte {
	var objpos string
	if pos := r.obj.Pos(); pos.IsValid() {
		objpos = fset.Position(pos).String()
	}
	return toJSON(&serial.ReferrersInitial{
		Desc:   r.obj.String(),
		ObjPos: objpos,
	})
}

// referrersPackageResult is the streaming result for one package of a "referrers" query.
type referrersPackageResult struct {
	pkg   *types.Package
	build *build.Context
	fset  *token.FileSet
	refs  []*ast.Ident // set of all other references to it
}

// forEachRef calls f(id, text) for id in r.refs, in order.
// Text is the text of the line on which id appears.
func (r *referrersPackageResult) foreachRef(f func(id *ast.Ident, text string)) {
	// Show referring lines, like grep.
	type fileinfo struct {
		refs     []*ast.Ident
		linenums []int            // line number of refs[i]
		data     chan interface{} // file contents or error
	}
	var fileinfos []*fileinfo
	fileinfosByName := make(map[string]*fileinfo)

	// First pass: start the file reads concurrently.
	sema := make(chan struct{}, 20) // counting semaphore to limit I/O concurrency
	for _, ref := range r.refs {
		posn := r.fset.Position(ref.Pos())
		fi := fileinfosByName[posn.Filename]
		if fi == nil {
			fi = &fileinfo{data: make(chan interface{})}
			fileinfosByName[posn.Filename] = fi
			fileinfos = append(fileinfos, fi)

			// First request for this file:
			// start asynchronous read.
			go func() {
				sema <- struct{}{} // acquire token
				content, err := readFile(r.build, posn.Filename, nil)
				<-sema // release token
				if err != nil {
					fi.data <- err
				} else {
					fi.data <- content
				}
			}()
		}
		fi.refs = append(fi.refs, ref)
		fi.linenums = append(fi.linenums, posn.Line)
	}

	// Second pass: print refs in original order.
	// One line may have several refs at different columns.
	for _, fi := range fileinfos {
		v := <-fi.data // wait for I/O completion

		// Print one item for all refs in a file that could not
		// be loaded (perhaps due to //line directives).
		if err, ok := v.(error); ok {
			var suffix string
			if more := len(fi.refs) - 1; more > 0 {
				suffix = fmt.Sprintf(" (+ %d more refs in this file)", more)
			}
			f(fi.refs[0], err.Error()+suffix)
			continue
		}

		lines := bytes.Split(v.([]byte), []byte("\n"))
		for i, ref := range fi.refs {
			f(ref, string(lines[fi.linenums[i]-1]))
		}
	}
}

// readFile is like ioutil.ReadFile, but
// it goes through the virtualized build.Context.
// If non-nil, buf must have been reset.
func readFile(ctxt *build.Context, filename string, buf *bytes.Buffer) ([]byte, error) {
	rc, err := buildutil.OpenFile(ctxt, filename)
	if err != nil {
		return nil, err
	}
	defer rc.Close()
	if buf == nil {
		buf = new(bytes.Buffer)
	}
	if _, err := io.Copy(buf, rc); err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

func (r *referrersPackageResult) PrintPlain(printf printfFunc) {
	r.foreachRef(func(id *ast.Ident, text string) {
		printf(id, "%s", text)
	})
}

func (r *referrersPackageResult) JSON(fset *token.FileSet) []byte {
	refs := serial.ReferrersPackage{Package: r.pkg.Path()}
	r.foreachRef(func(id *ast.Ident, text string) {
		refs.Refs = append(refs.Refs, serial.Ref{
			Pos:  fset.Position(id.NamePos).String(),
			Text: text,
		})
	})
	return toJSON(refs)
}
